Prepare build system for KDE Frameworks support
[quassel.git] / data / scripts / inxi
1 #!/usr/bin/env bash
2 ########################################################################
3 ####  Script Name: inxi
4 ####  Version: 2.1.2
5 ####  Date: 2014-03-14
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-2014 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/svn: http://inxi.googlecode.com
29 ####  Script forums: http://techpatterns.com/forums/forum-33.html
30 ####  IRC support: irc.oftc.net channel #smxi
31 ####
32 ####  This program is free software; you can redistribute it and/or modify
33 ####  it under the terms of the GNU General Public License as published by
34 ####  the Free Software Foundation; either version 3 of the License, or
35 ####  (at your option) any later version.
36 ####
37 ####  This program is distributed in the hope that it will be useful,
38 ####  but WITHOUT ANY WARRANTY; without even the implied warranty of
39 ####  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40 ####  GNU General Public License for more details.
41 ####
42 ####  You should have received a copy of the GNU General Public License
43 ####  along with this program.  If not, see <http://www.gnu.org/licenses/>.
44 ####
45 ####  If you don't understand what Free Software is, please read (or reread)
46 ####  this page: http://www.gnu.org/philosophy/free-sw.html
47 ########################################################################
48 ####  * Package names in (...) are the Debian Squeeze package name. Check your 
49 ####    distro for proper package name by doing this: which <application> 
50 ####    then find what package owns that application file. Or run --recommends
51 ####    which shows package names for Debian/Ubuntu, Arch, and Fedora/Redhat/Suse
52 ####
53 ####  DEPENDENCIES
54 ####  * bash >=3.0 (bash); df, readlink, stty, tr, uname, wc (coreutils);
55 ####    gawk (gawk); grep (grep); lspci (pciutils);
56 ####    ps, uptime (procps); find (findutils)
57 ####  * Also the proc filesystem should be present and mounted
58 ####  * Some features, like -M and -d will not work, or will work incompletely,
59 ####    if /sys is missing
60 ####
61 ####    Apparently unpatched bash 3.0 has arrays broken; bug reports:
62 ####    http://ftp.gnu.org/gnu/bash/bash-3.0-patches/bash30-008
63 ####    http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00144.html
64 ####  Bash 3.1 for proper array use
65 ####
66 ####    Arrays work in bash 2.05b, but "grep -Em" does not
67 ####
68 ####  RECOMMENDS (Needed to run certain features, listed by option)
69 ####  -A - for output of usb audio information: lsusb (usbutils)
70 ####  -Ax -Nx - for audio/network module version: modinfo (module-init-tools)
71 ####  -Dx - for hdd temp output (root only default): hddtemp (hddtemp)
72 ####       For user level hdd temp output: sudo (sudo)
73 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
74 ####  -G - full graphics output requires:  glxinfo (mesa-utils); xdpyinfo (X11-utils);
75 ####       xrandr (x11-xserver-utils)
76 ####  -i - IP information, local/wan - ip (iproute) legacy, not used if ip present: ifconfig (net-tools)
77 ####  -Ix - view current runlevel while not in X window system (or with -x): runlevel (sysvinit)
78 ####  -M - for older systems whose kernel does not have /sys data for machine, dmidecode (dmidecode)
79 ####  -o - for unmounted file system information in unmounted drives (root only default): file (file)
80 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
81 ####       For user level unmounted file system type output: sudo (sudo)
82 ####  -s   For any sensors output, fan, temp, etc: sensors (lm-sensors)
83 ####       Note: requires setup of lm-sensors (sensors-detect and adding modules/modprobe/reboot,
84 ####       and ideally, pwmconfig) prior to full output being available. 
85 ####  -S   For desktop environment, user must be in X and have xprop installed (in X11-utils)
86 ########################################################################
87 ####  BSD Adjustments
88 ####  * sed -i '' form supported by using SED_I="-i ''".
89 ####  * Note: New BSD sed supports using -r instead of -E for compatibility with gnu sed
90 ####    However, older, like FreeBSD 7.x, does not have -r so using SED_RX='-E' for this.
91 ####  * Gnu grep options can be used if the function component is only run in linux
92 ####    These are the options that bsd grep does not support that inxi uses: -m <number> -o 
93 ####    so make sure if you use those to have them in gnu/linux only sections.
94 ####    It appears that freebsd uses gnu grep but openbsd uses bsd grep, however.
95 ####  * BSD ps does not support --without-headers option, and also does not support --sort <option>
96 ####    Tests show that -m fails to sort memory as expected, but -r does sort cpu percentage.
97 ####  * BSD_TYPE is set with values null, debian-bsd (debian gnu/kfreebsd), bsd (all other bsds)
98 ####  * Subshell and array closing ) must not be on their own line unless you use an explicit \ 
99 ####    to indicate that logic continues to next line where closing ) or )) are located.
100 ########################################################################
101 ####  CONVENTIONS:
102 ####  * Character Encoding: UTF-8 - this file contains special characters that must be opened and saved as UTF8
103 ####  * Indentation: TABS
104 ####  * Do not use `....` (back quotes), those are totally non-reabable, use $(....).
105 ####  * Do not use one liner flow controls. 
106 ####    The ONLY time you should use ';' (semi-colon) is in this single case: if [[ condition ]];then.
107 ####    Never use compound 'if': ie, if [[ condition ]] && statement.
108 ####  * Note: [[ -n $something ]] - double brackets does not require quotes for variables: ie, "$something".
109 ####  * Always use quotes, double or single, for all string values.
110 ####  * All new code/methods must be in a function.
111 ####  * For all boolean tests, use 'true' / 'false'.
112 ####    !! Do NOT use 0 or 1 unless it's a function return. 
113 ####  * Avoid complicated tests in the if condition itself.
114 ####  * To 'return' a value in a function, use 'echo <var>'.
115 ####  * For gawk: use always if ( num_of_cores > 1 ) { hanging { starter for all blocks
116 ####    This lets us use one method for all gawk structures, including BEGIN/END, if, for, etc
117 ####
118 ####  VARIABLE/FUNCTION NAMING:
119 ####  * All functions should follow standard naming--verb adjective noun. 
120 ####      ie, get_cpu_data
121 ####  * All variables MUST be initialized / declared explicitly, either top of file, for Globals, or using local
122 ####  * All variables should clearly explain what they are, except counters like i, j.
123 ####  * Each word of Bash variable must be separated by '_' (underscore) (camel form), like: cpu_data
124 ####  * Each word of Gawk variable must be like this (first word lower, following start with upper): cpuData
125 ####  * Global variables are 'UPPER CASE', at top of this file.
126 ####      ie, SOME_VARIABLE=''
127 ####  * Local variables are 'lower case' and declared at the top of the function using local, always.
128 ####      ie: local some_variable=''
129 ####  * Locals that will be inherited by child functions have first char capitalized (so you know they are inherited).
130 ####      ie, Some_Variable 
131 ####  * Booleans should start with b_ (local) or B_ (global) and state clearly what is being tested.
132 ####  * Arrays should start with a_ (local) or A_ (global).
133 ####
134 ####  SPECIAL NOTES:
135 ####  * The color variable ${C2} must always be followed by a space unless you know what
136 ####    character is going to be next for certain. Otherwise irc color codes can be accidentally
137 ####    activated or altered.
138 ####  * For native script konversation support (check distro for correct konvi scripts path):
139 ####    ln -s <path to inxi> /usr/share/apps/konversation/scripts/inxi
140 ####    DCOP doesn't like \n, so avoid using it for most output unless required, as in error messages.
141 ####  * print_screen_output " " # requires space, not null, to avoid error in for example in irssi
142 ####  * For logging of array data, array must be placed into the temp_array, otherwise only the first key logs
143 ####  * In gawk search patterns, . is a wildcard EXCEPT in [0-9.] type containers, then it's a literal
144 ####    So outside of bracketed items, it must be escaped, \. but inside, no need. Outside of gawk it should 
145 ####    be escaped in search patterns if you are using it as a literal.
146 ####  
147 ####  PACKAGE MANAGER DATA (note, while inxi tries to avoid using package managers to get data, sometimes 
148 ####  it's the only way to get some data):
149 ####  * dpkg options: http://www.cyberciti.biz/howto/question/linux/dpkg-cheat-sheet.php
150 ####  * pacman options: https://wiki.archlinux.org/index.php/Pacman_Rosetta
151 ####
152 ####  As with all 'rules' there are acceptions, these are noted where used.
153 ###################################################################################
154 ####    KDE Konversation information.  Moving from dcop(qt3/KDE3) to dbus(qt4/KDE4)
155 ###################################################################################
156 ####  * dcop and dbus   -- these talk back to Konversation from this program
157 ####  * Scripting info  -- http://konversation.berlios.de/docs/scripting.html
158 ####    -- http://www.kde.org.uk/apps/konversation/
159 ####  * dbus info       -- http://dbus.freedesktop.org/doc/dbus-tutorial.html
160 ####    view dbus info  -- https://fedorahosted.org/d-feet/
161 ####    -- or run qdbus
162 ####  * Konvi dbus/usage-- qdbus org.kde.konversation /irc say <server> <target-channel> <output>
163 ####  * Python usage    -- http://wiki.python.org/moin/DbusExamples  (just in case)
164 ####
165 ####    Because webpages come and go, the above information needs to be moved to inxi's wiki
166 ########################################################################
167 ####  Valuable Resources
168 ####  CPU flags: http://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean
169 ####  Advanced Bash: http://wiki.bash-hackers.org/syntax/pe
170 ####  gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html
171 ####  raid mdstat: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
172 ####               http://www.howtoforge.com/replacing_hard_disks_in_a_raid1_array
173 ####               https://raid.wiki.kernel.org/index.php/Mdstat
174 ########################################################################
175 ####  TESTING FLAGS
176 ####  inxi supports advanced testing triggers to do various things, using -! <arg>
177 ####  -! 1  - triggers default B_TESTING_1='true' to trigger some test or other
178 ####  -! 2  - triggers default B_TESTING_2='true' to trigger some test or other
179 ####  -! 3  - triggers B_TESTING_1='true' and B_TESTING_2='true'
180 ####  -! 10 - triggers an update from the primary dev download server instead of svn
181 ####  -! 11 - triggers an update from svn branch one - if present, of course
182 ####  -! 12 - triggers an update from svn branch two - if present, of course
183 ####  -! 13 - triggers an update from svn branch three - if present, of course
184 ####  -! 14 - triggers an update from svn branch four - if present, of course
185 ####  -! <http://......> - Triggers an update from whatever server you list.
186 ####  LOG FLAGS (logs to $HOME/.inxi/inxi.log with rotate 3 total)
187 ####  -@ 8  - Basic data logging of generated data / array values
188 ####  -@ 9  - Full logging of all data used, including cat of files and system data
189 ####  -@ 10 - Basic data logging plus color code logging
190 ########################################################################
191 #### VARIABLES
192 ########################################################################
193
194 ## NOTE: we can use hwinfo if it's available in all systems, or most, to get
195 ## a lot more data and verbosity levels going
196
197 ### DISTRO MAINTAINER FLAGS ###
198 # flag to allow distro maintainers to turn off update features. If false, turns off
199 # -U and -! testing/advanced update options, as well as removing the -U help menu item
200 # NOTE: Usually you want to create these in /etc/inxi.conf to avoid having to update each time
201 B_ALLOW_UPDATE='true'
202 B_ALLOW_WEATHER='true'
203
204 ### USER CONFIGS: SET IN inxi.conf file see wiki for directions ###
205 # http://code.google.com/p/inxi/wiki/script_configuration_files
206 # override in user config if desired, seems like less than .3 doesn't work as reliably
207 CPU_SLEEP='0.3' 
208 FILTER_STRING='<filter>'
209
210 # for features like help/version will fit to terminal / console screen width. Console
211 # widths will be dynamically set in main() based on cols in term/console
212 COLS_MAX_CONSOLE='115'
213 COLS_MAX_IRC='105'
214 PS_COUNT=5
215 # change to less, or more if you have very slow connection
216 WGET_TIMEOUT=8
217 ### END USER CONFIGS ###
218
219 ### LOCALIZATION - DO NOT CHANGE! ###
220 # set to default LANG to avoid locales errors with , or .
221 LANG=C
222 # Make sure every program speaks English.
223 LC_ALL="C"
224 export LC_ALL
225
226 ### ARRAYS ###
227 ## Prep
228 # Clear nullglob, because it creates unpredictable situations with IFS=$'\n' ARR=($VAR) IFS="$ORIGINAL_IFS"
229 # type constructs. Stuff like [rev a1] is now seen as a glob expansion pattern, and fails, and
230 # therefore results in nothing.
231 shopt -u nullglob
232 ## info on bash built in: $IFS - http://tldp.org/LDP/abs/html/internalvariables.html
233 # Backup the current Internal Field Separator
234 ORIGINAL_IFS="$IFS"
235
236 ## Initialize
237 A_ALSA_DATA=''
238 A_AUDIO_DATA=''
239 A_CMDL=''
240 A_CPU_CORE_DATA=''
241 A_CPU_DATA=''
242 A_CPU_TYPE_PCNT_CCNT=''
243 A_DEBUG_BUFFER=''
244 A_GCC_VERSIONS=''
245 A_GLX_DATA=''
246 A_GRAPHICS_CARD_DATA=''
247 A_GRAPHIC_DRIVERS=''
248 A_HDD_DATA=''
249 A_INIT_DATA=''
250 A_INTERFACES_DATA=''
251 A_MACHINE_DATA=''
252 A_NETWORK_DATA=''
253 A_OPTICAL_DRIVE_DATA=''
254 A_PARTITION_DATA=''
255 A_PCICONF_DATA=''
256 A_PS_DATA=''
257 A_RAID_DATA=''
258 A_SENSORS_DATA=''
259 A_UNMOUNTED_PARTITION_DATA=''
260 A_WEATHER_DATA=''
261 A_DISPLAY_SERVER_DATA=''
262
263 ### BOOLEANS ###
264 ## standard boolean flags ##
265 B_BSD_RAID='false'
266 B_COLOR_SCHEME_SET='false'
267 B_CONSOLE_IRC='false'
268 # triggers full display of cpu flags
269 B_CPU_FLAGS_FULL='false'
270 # test for dbus irc client
271 B_DBUS_CLIENT='false'
272 # kde dcop
273 B_DCOP='false'
274 # Debug flood override: make 'true' to allow long debug output
275 B_DEBUG_FLOOD='false'
276 B_DMIDECODE_SET='false'
277 # show extra output data
278 B_EXTRA_DATA='false'
279 # triggered by -xx
280 B_EXTRA_EXTRA_DATA='false'
281 B_ID_SET='false'
282 # override certain errors due to currupted data
283 B_HANDLE_CORRUPT_DATA='false'
284 B_LABEL_SET='false'
285 B_LSPCI='false'
286 B_LOG_COLORS='false'
287 B_LOG_FULL_DATA='false'
288 B_MAPPER_SET='false'
289 B_OUTPUT_FILTER='false'
290 B_OVERRIDE_FILTER='false'
291 B_PCICONF='false'
292 B_PCICONF_SET='false'
293 # kde qdbus
294 B_QDBUS='false'
295 B_PORTABLE='false'
296 B_RAID_SET='false'
297 B_ROOT='false'
298 B_RUN_COLOR_SELECTOR='false'
299 B_RUNNING_IN_DISPLAY='false' # in x type display server
300 if tty >/dev/null;then
301         B_RUNNING_IN_SHELL='true'
302 else
303         B_RUNNING_IN_SHELL='false'
304 fi
305 # this sets the debug buffer
306 B_SCRIPT_UP='false'
307 B_SHOW_ADVANCED_NETWORK='false'
308 # Show sound card data
309 B_SHOW_AUDIO='false'
310 B_SHOW_BASIC_RAID='false'
311 B_SHOW_BASIC_CPU='false'
312 B_SHOW_BASIC_DISK='false'
313 B_SHOW_BASIC_OPTICAL='false'
314 B_SHOW_CPU='false'
315 B_SHOW_DISPLAY_DATA='false'
316 B_SHOW_DISK_TOTAL='false'
317 B_SHOW_DISK='false'
318 # Show full hard disk output
319 B_SHOW_FULL_HDD='false'
320 B_SHOW_FULL_OPTICAL='false'
321 B_SHOW_GRAPHICS='false'
322 # Set this to 'false' to avoid printing the hostname, can be set false now
323 B_SHOW_HOST='true'
324 B_SHOW_INFO='false'
325 B_SHOW_IP='false'
326 B_SHOW_LABELS='false'
327 B_SHOW_MACHINE='false'
328 B_SHOW_NETWORK='false'
329 # either -v > 3 or -P will show partitions
330 B_SHOW_PARTITIONS='false'
331 B_SHOW_PARTITIONS_FULL='false'
332 B_SHOW_PS_CPU_DATA='false'
333 B_SHOW_PS_MEM_DATA='false'
334 B_SHOW_RAID='false'
335 # because many systems have no mdstat file, -b/-F should not show error if no raid file found
336 B_SHOW_RAID_R='false' 
337 B_SHOW_REPOS='false'
338 B_SHOW_SENSORS='false'
339 # triggers only short inxi output
340 B_SHOW_SHORT_OUTPUT='false'
341 B_SHOW_SYSTEM='false'
342 B_SHOW_UNMOUNTED_PARTITIONS='false'
343 B_SHOW_UUIDS='false'
344 B_SHOW_WEATHER='false'
345 B_SYSCTL='false'
346 # triggers various debugging and new option testing
347 B_TESTING_1='false'
348 B_TESTING_2='false'
349 B_UPLOAD_DEBUG_DATA='false'
350 B_USB_NETWORKING='false'
351 # set to true here for debug logging from script start
352 B_USE_LOGGING='false'
353 B_UUID_SET='false'
354 B_XORG_LOG='false'
355
356 ## Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]]
357 B_ASOUND_DEVICE_FILE='false'
358 B_ASOUND_VERSION_FILE='false'
359 B_BASH_ARRAY='false'
360 B_CPUINFO_FILE='false'
361 B_DMESG_BOOT_FILE='false' # bsd only
362 B_LSB_FILE='false'
363 B_MDSTAT_FILE='false'
364 B_MEMINFO_FILE='false'
365 B_MODULES_FILE='false' #
366 B_MOUNTS_FILE='false'
367 B_OS_RELEASE_FILE='false' # new default distro id file? will this one work where lsb-release didn't?
368 B_PARTITIONS_FILE='false' #
369 B_PROC_DIR='false'
370 B_SCSI_FILE='false'
371
372 ## app tested for and present, to avoid repeat tests
373 B_FILE_TESTED='false'
374 B_HDDTEMP_TESTED='false'
375 B_MODINFO_TESTED='false'
376 B_SUDO_TESTED='false'
377
378 ### CONSTANTS/INITIALIZE - SOME MAY BE RESET LATER ###
379 DCOPOBJ="default"
380 DEBUG=0 # Set debug levels from 1-10 (8-10 trigger logging levels)
381 # Debug Buffer Index, index into a debug buffer storing debug messages until inxi is 'all up'
382 DEBUG_BUFFER_INDEX=0
383 ## note: the debugger rerouting to /dev/null has been moved to the end of the get_parameters function
384 ## so -@[number] debug levels can be set if there is a failure, otherwise you can't even see the errors
385 SED_I='-i' # for gnu sed, will be set to -i '' for bsd sed
386 SED_RX='-r' # for gnu sed, will be set to -E for bsd sed for backward compatibility
387
388 # default to false, no konversation found, 1 is native konvi (qt3/KDE3) script mode, 2 is /cmd inxi start,
389 ##      3 is Konversation > 1.2 (qt4/KDE4) 
390 KONVI=0
391 # NO_CPU_COUNT=0        # Wether or not the string "dual" or similar is found in cpuinfo output. If so, avoid dups.
392 # This is a variable that controls how many parameters inxi will parse in a /proc/<pid>/cmdline file before stopping.
393 PARAMETER_LIMIT=30
394 SCHEME=0 # set default scheme - do not change this, it's set dynamically
395 # this is set in user prefs file, to override dynamic temp1/temp2 determination of sensors output in case
396 # cpu runs colder than mobo
397 SENSORS_CPU_NO=''
398 # SHOW_IRC=1 to avoid showing the irc client version number, or SHOW_IRC=0 to disable client information completely.
399 SHOW_IRC=2
400 # Verbosity level defaults to 0, this can also be set with -v0, -v2, -v3, etc as a parameter.
401 VERBOSITY_LEVEL=0
402 # Supported number of verbosity levels, including 0
403 VERBOSITY_LEVELS=7
404
405 ### LOGGING ###
406 ## logging eval variables, start and end function: Insert to LOGFS LOGFE when debug level >= 8
407 LOGFS_STRING='log_function_data fs $FUNCNAME "$( echo $@ )"'
408 LOGFE_STRING='log_function_data fe $FUNCNAME'
409 LOGFS=''
410 LOGFE=''
411 # uncomment for debugging from script start
412 # LOGFS=$LOGFS_STRING
413 # LOGFE=$LOGFE_STRING
414
415 ### FILE NAMES/PATHS/URLS - must be non root writable ###
416 # File's used when present
417 FILE_ASOUND_DEVICE='/proc/asound/cards'
418 FILE_ASOUND_MODULES='/proc/asound/modules' # not used but maybe for -A?
419 FILE_ASOUND_VERSION='/proc/asound/version'
420 FILE_CPUINFO='/proc/cpuinfo'
421 FILE_DMESG_BOOT='/var/run/dmesg.boot'
422 FILE_LSB_RELEASE='/etc/lsb-release'
423 FILE_MDSTAT='/proc/mdstat'
424 FILE_MEMINFO='/proc/meminfo'
425 FILE_MODULES='/proc/modules'
426 FILE_MOUNTS='/proc/mounts'
427 FILE_OS_RELEASE='/etc/os-release'
428 FILE_PARTITIONS='/proc/partitions'
429 FILE_SCSI='/proc/scsi/scsi'
430 FILE_XORG_LOG='/var/log/Xorg.0.log' # if not found, search and replace with actual location
431
432 FILE_PATH=''
433 HDDTEMP_PATH=''
434 MODINFO_PATH=''
435 SUDO_PATH=''
436
437 SCRIPT_DATA_DIR="$HOME/.inxi"
438 ALTERNATE_FTP='' # for data uploads
439 ALTERNATE_WEATHER_LOCATION='' # weather alternate location
440 LOG_FILE="$SCRIPT_DATA_DIR/inxi.log"
441 LOG_FILE_1="$SCRIPT_DATA_DIR/inxi.1.log"
442 LOG_FILE_2="$SCRIPT_DATA_DIR/inxi.2.log"
443 MAN_FILE_DOWNLOAD='http://inxi.googlecode.com/svn/trunk/inxi.1.gz'
444 MAN_FILE_LOCATION='/usr/share/man/man1'
445 SCRIPT_NAME='inxi'
446 SCRIPT_PATCH_NUMBER=''
447 SCRIPT_PATH='' #filled-in in Main
448 SCRIPT_VERSION_NUMBER=""        #filled-in in Main
449 SCRIPT_DOWNLOAD='http://inxi.googlecode.com/svn/trunk/'
450 SCRIPT_DOWNLOAD_BRANCH_1='http://inxi.googlecode.com/svn/branches/one/'
451 SCRIPT_DOWNLOAD_BRANCH_2='http://inxi.googlecode.com/svn/branches/two/'
452 SCRIPT_DOWNLOAD_BRANCH_3='http://inxi.googlecode.com/svn/branches/three/'
453 SCRIPT_DOWNLOAD_BRANCH_4='http://inxi.googlecode.com/svn/branches/four/'
454 SCRIPT_DOWNLOAD_BRANCH_BSD='http://inxi.googlecode.com/svn/branches/bsd/'
455 SCRIPT_DOWNLOAD_BRANCH_GNUBSD='http://inxi.googlecode.com/svn/branches/gnubsd/'
456 SCRIPT_DOWNLOAD_DEV='http://smxi.org/test/'
457 # note, you can use any ip url here as long as it's the only line on the output page.
458 # Also the ip address must be the last thing on that line.
459 WAN_IP_URL='http://smxi.org/opt/ip.php'
460 KONVI_CFG="konversation/scripts/$SCRIPT_NAME.conf" # relative path to $(kde-config --path data)
461
462 ### INITIALIZE VARIABLES NULL ###
463 BSD_TYPE=''
464 BSD_VERSION=
465 CMDL_MAX=''
466
467 DEV_DISK_ID=''
468 DEV_DISK_LABEL=''
469 DEV_DISK_MAPPER=''
470 DEV_DISK_UUID=''
471 DMIDECODE_DATA=''
472 IRC_CLIENT=''
473 IRC_CLIENT_VERSION=''
474 PS_THROTTLED=''
475 REPO_DATA=''
476
477 ### LAYOUT ###
478 # These two determine separators in single line output, to force irc clients not to break off sections
479 SEP1='~'
480 SEP2=' '
481 # these will assign a separator to non irc states. Important! Using ':' can trigger stupid emoticon
482 # behaviors in output on IRC, so do not use those.
483 SEP3_IRC=''
484 SEP3_CONSOLE=':'
485 SEP3='' # do not set, will be set dynamically
486
487 # Default indentation level. NOTE: actual indent is 1 greater to allow for spacing
488 INDENT=10
489
490 ### COLUMN WIDTHS ###
491 COLS_INNER='' ## for width minus INDENT
492 COLS_MAX=''
493
494 TERM_COLUMNS=80
495 TERM_LINES=100
496
497 ## sometimes will trigger an error (mageia) if not in shell
498 if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
499         if [[ -n $( type -p tput ) ]];then
500                 TERM_COLUMNS=$(tput cols)
501                 TERM_LINES=$(tput lines)
502         fi
503         # double check, just in case it's missing functionality or whatever
504         if [[ -n ${TERM_COLUMNS##[0-9]*} ]];then
505                 TERM_COLUMNS=80
506                 TERM_LINES=100
507         fi
508 fi
509
510 # Only for legacy user config files se we can test and convert the var name
511 LINE_MAX_CONSOLE=''
512 LINE_MAX_IRC=''
513
514 ### COLORS ###
515 # Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Use following variables in config 
516 # files to change defaults for each type, or global
517 # Same as runtime parameter.
518 DEFAULT_COLOR_SCHEME=2
519 ## color variables - set dynamically
520 COLOR_SCHEME=''
521 C1=''
522 C2=''
523 CN=''
524 ## Always leave these blank, these are only going to be set in inxi.conf files, that makes testing
525 ## for user changes easier after sourcing the files
526 GLOBAL_COLOR_SCHEME=''
527 IRC_COLOR_SCHEME=''
528 IRC_CONS_COLOR_SCHEME=''
529 IRC_X_TERM_COLOR_SCHEME=''
530 CONSOLE_COLOR_SCHEME=''
531 VIRT_TERM_COLOR_SCHEME=''
532
533 ## Output colors
534 # A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below.
535 unset EMPTY
536 #             DGREY   BLACK   RED     DRED    GREEN   DGREEN  YELLOW  DYELLOW
537 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"
538 IRC_COLORS="  \x0314  \x0301  \x0304  \x0305  \x0309  \x0303  \x0308  \x0307"
539 #                          BLUE    DBLUE   MAGENTA DMAGENTA CYAN   DCYAN   WHITE   GREY    NORMAL
540 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"
541 IRC_COLORS=" $IRC_COLORS    \x0312 \x0302  \x0313  \x0306  \x0311  \x0310  \x0300  \x0315  \x03"
542
543 #ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS)
544 A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL )
545
546 # See above for notes on EMPTY
547 ## note: group 1: 0, 1 are null/normal
548 ## Following: group 2: generic, light/dark or dark/light; group 3: dark on light; group 4 light on dark; 
549 # this is the count of the first two groups, starting at zero
550 SAFE_COLOR_COUNT=12
551 A_COLOR_SCHEMES=( 
552 EMPTY,EMPTY,EMPTY 
553 NORMAL,NORMAL,NORMAL 
554
555 BLUE,NORMAL,NORMAL
556 BLUE,RED,NORMAL 
557 CYAN,BLUE,NORMAL 
558 DCYAN,NORMAL,NORMAL
559 DCYAN,BLUE,NORMAL 
560 DGREEN,NORMAL,NORMAL 
561 DYELLOW,NORMAL,NORMAL 
562 GREEN,DGREEN,NORMAL 
563 GREEN,NORMAL,NORMAL 
564 MAGENTA,NORMAL,NORMAL
565 RED,NORMAL,NORMAL
566
567 BLACK,DGREY,NORMAL
568 DBLUE,DGREY,NORMAL 
569 DBLUE,DMAGENTA,NORMAL
570 DBLUE,DRED,NORMAL 
571 DBLUE,BLACK,NORMAL
572 DGREEN,DYELLOW,NORMAL 
573 DYELLOW,BLACK,NORMAL
574 DMAGENTA,BLACK,NORMAL
575 DCYAN,DBLUE,NORMAL
576
577 WHITE,GREY,NORMAL
578 GREY,WHITE,NORMAL
579 CYAN,GREY,NORMAL 
580 GREEN,WHITE,NORMAL 
581 GREEN,YELLOW,NORMAL 
582 YELLOW,WHITE,NORMAL 
583 MAGENTA,CYAN,NORMAL 
584 MAGENTA,YELLOW,NORMAL
585 RED,CYAN,NORMAL
586 RED,WHITE,NORMAL 
587 BLUE,WHITE,NORMAL
588 )
589
590 # WARNING: In the main part below (search for 'KONVI')
591 # there's a check for Konversation-specific config files.
592 # Any one of these can override the above if inxi is run
593 # from Konversation!
594
595 ## DISTRO DATA/ID ##
596 # In cases of derived distros where the version file of the base distro can also be found under /etc,
597 # the derived distro's version file should go first. (Such as with Sabayon / Gentoo)
598 DISTROS_DERIVED="antix-version aptosid-version kanotix-version knoppix-version mandrake-release pardus-release sabayon-release siduction-version sidux-version solusos-release turbolinux-release zenwalk-version"
599 # debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu.
600 DISTROS_EXCLUDE_LIST="debian_version ubuntu_version"
601 DISTROS_PRIMARY="arch-release gentoo-release redhat-release slackware-version SuSE-release"
602 DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release"
603 # this is being used both by core distros and derived distros now, eg, solusos 1 uses it for solusos id, while
604 # debian, solusos base, uses it as well, so we have to know which it is.
605 DISTROS_OS_RELEASE_GOOD="arch-release SuSE-release"
606 ## Distros with known problems
607 # DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output
608 # Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially
609
610 ## OUTPUT FILTERS/SEARCH ##
611 # Note that \<ltd\> bans only words, not parts of strings; in \<corp\> you can't use punctuation characters like . or ,
612 # we're saving about 10+% of the total script exec time by hand building the ban lists here, using hard quotes.
613 BAN_LIST_NORMAL='chipset|components|computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|industrial|international|revision|semiconductor|software|technologies|technology|ltd\.|\<ltd\>|inc\.|\<inc\>|intl\.|co\.|\<co\>|corp\.|\<corp\>|\(tm\)|\(r\)|®|\(rev ..\)'
614 BAN_LIST_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]'
615
616 SENSORS_GPU_SEARCH='intel|radeon|nouveau'
617
618 ### USB networking search string data, because some brands can have other products than
619 ### wifi/nic cards, they need further identifiers, with wildcards.
620 ### putting the most common and likely first, then the less common, then some specifics
621 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"
622 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" 
623 # then a few known hard to ID ones added 
624 # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; 
625 USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
626
627 ########################################################################
628 #### MAIN: Where it all begins
629 ########################################################################
630 main()
631 {
632         eval $LOGFS
633         
634         local color_scheme=''
635         # this will be used by all functions following
636         local Ps_aux_Data="$( ps aux )"
637
638         # This function just initializes variables
639         initialize_data
640         
641         # Source global config overrides, needs to be here because some things
642         # can be reset that were set in initialize, but check_required_apps needs
643         if [[ -s /etc/$SCRIPT_NAME.conf ]];then
644                 source /etc/$SCRIPT_NAME.conf
645         fi
646         # Source user config variables override /etc/inxi.conf variables
647         if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then
648                 source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf
649         fi
650         # Convert to new variable names if set in config files, legacy test
651         if [[ -n $LINE_MAX_CONSOLE ]];then
652                 COLS_MAX_CONSOLE=$LINE_MAX_CONSOLE
653         fi
654         if [[ -n $LINE_MAX_IRC ]];then
655                 COLS_MAX_IRC=$LINE_MAX_IRC
656         fi
657         # TERM_COLUMNS is set in top globals, using tput cols
658         if [[ $TERM_COLUMNS -lt $COLS_MAX_CONSOLE ]];then
659                 COLS_MAX_CONSOLE=$TERM_COLUMNS
660         fi
661         # adjust, some terminals will wrap if output cols == term cols
662         COLS_MAX_CONSOLE=$(( $COLS_MAX_CONSOLE - 2 ))
663         
664         # comes after source for user set stuff
665         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
666                 COLS_MAX=$COLS_MAX_CONSOLE
667                 SEP3=$SEP3_CONSOLE
668         else
669                 # too hard to read if no colors, so force that for users on irc
670                 if [[ $SCHEME == 0 ]];then
671                         SEP3=$SEP3_CONSOLE
672                 else
673                         SEP3=$SEP3_IRC
674                 fi
675                 COLS_MAX=$COLS_MAX_IRC
676         fi
677         
678         COLS_INNER=$(( $COLS_MAX - $INDENT - 1 ))
679         # Check for dependencies BEFORE running ANYTHING else except above functions
680         # Not all distro's have these depends installed by default. Don't want to run
681         # this if the user is requesting to see this information in the first place
682         # Only continue if required apps tests ok
683         if [[ $1 != '--recommends' ]];then
684                 check_required_apps
685                 check_recommended_apps
686         fi
687
688         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
689         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
690         
691         # previous source location, check for bugs
692
693         ## this needs to run before the KONVI stuff is set below
694         ## Konversation 1.2 apparently does not like the $PPID test in get_start_client
695         ## So far there is no known way to detect if qt4_konvi is the parent process
696         ## this method will infer qt4_konvi as parent
697         get_start_client
698
699         # note: this only works if it's run from inside konversation as a script builtin or something
700         # only do this if inxi has been started as a konversation script, otherwise bypass this 
701 #       KONVI=3 ## for testing puroses
702         if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then
703                 if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3))    
704                         DCPORT="$1"
705                         DCSERVER="$2"
706                         DCTARGET="$3"
707                         shift 3
708                 elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4))
709                         DCSERVER="$1" ##dbus testing
710                         DCTARGET="$2" ##dbus testing
711                         shift 2
712                 fi
713
714                 # The section below is on request of Argonel from the Konversation developer team:
715                 # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
716                 IFS=":"
717                 for kde_config in $( kde-config --path data )
718                 do
719                         if [[ -r ${kde_config}${KONVI_CFG} ]];then
720                                 source "${kde_config}${KONVI_CFG}"
721                                 break
722                         fi
723                 done
724                 IFS="$ORIGINAL_IFS"
725         fi
726
727         ## leave this for debugging dcop stuff if we get that working
728         #       print_screen_output "DCPORT: $DCPORT"
729         #       print_screen_output "DCSERVER: $DCSERVER"
730         #       print_screen_output "DCTARGET: $DCTARGET"
731         
732         # first init function must be set first for colors etc. Remember, no debugger
733         # stuff works on this function unless you set the debugging flag manually.
734         # Debugging flag -@ [number] will not work until get_parameters runs.
735         
736         # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter.
737         # must be here to allow debugger and other flags to be set.
738         get_parameters "$@"
739
740         # If no colorscheme was set in the parameter handling routine, then set the default scheme
741         if [[ $B_COLOR_SCHEME_SET != 'true' ]];then
742                 # This let's user pick their color scheme. For IRC, only shows the color schemes, no interactive
743                 # The override value only will be placed in user config files. /etc/inxi.conf can also override
744                 if [[ $B_RUN_COLOR_SELECTOR == 'true' ]];then 
745                         select_default_color_scheme
746                 else
747                         # set the default, then override as required
748                         color_scheme=$DEFAULT_COLOR_SCHEME
749                         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
750                                 color_scheme=$GLOBAL_COLOR_SCHEME
751                         else
752                                 if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
753                                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
754                                                 color_scheme=$CONSOLE_COLOR_SCHEME
755                                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
756                                                 color_scheme=$VIRT_TERM_COLOR_SCHEME
757                                         fi
758                                 else
759                                         if [[ -n $IRC_X_TERM_COLOR_SCHEME && $B_CONSOLE_IRC == 'true' && -n $B_RUNNING_IN_DISPLAY ]];then
760                                                 color_scheme=$IRC_X_TERM_COLOR_SCHEME
761                                         elif [[ -n $IRC_CONS_COLOR_SCHEME && -z $DISPLAY ]];then
762                                                 color_scheme=$IRC_CONS_COLOR_SCHEME
763                                         elif [[ -n $IRC_COLOR_SCHEME ]];then
764                                                 color_scheme=$IRC_COLOR_SCHEME
765                                         fi
766                                 fi
767                         fi
768                         set_color_scheme $color_scheme
769                 fi
770         fi
771         
772         # all the pre-start stuff is in place now
773         B_SCRIPT_UP='true'
774         script_debugger "Debugger: $SCRIPT_NAME is up and running..."
775         
776         # then create the output
777         print_it_out
778
779         ## last steps
780         if [[ $B_RUNNING_IN_SHELL == 'true' && $SCHEME -gt 0 ]];then
781                 echo -n "\e[0m"
782         fi
783         eval $LOGFE
784         # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code
785         # from the last command is taken..
786         exit 0
787 }
788
789 #### -------------------------------------------------------------------
790 #### basic tests: set script data, booleans, PATH, version numbers
791 #### -------------------------------------------------------------------
792
793 # Set PATH data so we can access all programs as user. Set BAN lists.
794 # initialize some boleans, these directories are used throughout the script
795 # some apps are used for extended functions any directory used, should be
796 # checked here first.
797 # No args taken.
798 initialize_data()
799 {
800         eval $LOGFS
801         BSD_VERSION=$( uname -s 2>/dev/null | tr '[A-Z]' '[a-z]' )
802         
803         # note: archbsd says they are a freebsd distro, so assuming it's the same as freebsd
804         if [[ -n $( grep 'bsd' <<< "$BSD_VERSION" ) ]];then
805                 # GNU/kfreebsd will by definition have GNU tools like sed/grep
806                 if [[ -n $( grep 'kfreebsd' <<< "$BSD_VERSION" ) ]];then
807                         BSD_TYPE='debian-bsd' # debian gnu bsd
808                 else
809                         BSD_TYPE='bsd' # all other bsds
810                         SED_I="-i ''"
811                         SED_RX='-E'
812                 fi
813         fi
814         # now set the script BOOLEANS for files required to run features
815         # note that freebsd has /proc but it's empty
816         if [[ -d "/proc/" && -z $BSD_TYPE ]];then
817                 B_PROC_DIR='true'
818         elif [[ -n $BSD_TYPE ]];then
819                 B_PROC_DIR='false'
820         else
821                 error_handler 6
822         fi
823         
824         initialize_paths
825         
826         if [[ -n $BSD_TYPE ]];then
827                 if [[ -e $FILE_DMESG_BOOT ]];then
828                         B_DMESG_BOOT_FILE='true'
829                 fi
830         else
831                 # found a case of battery existing but having nothing in it on desktop mobo
832                 # not all laptops show the first, 
833                 if [[ -n $( ls /proc/acpi/battery 2>/dev/null ) ]];then
834                         B_PORTABLE='true'
835                 fi
836         fi
837         
838         
839         if [[ -e $FILE_CPUINFO ]]; then
840                 B_CPUINFO_FILE='true'
841         fi
842
843         if [[ -e $FILE_MEMINFO ]];then
844                 B_MEMINFO_FILE='true'
845         fi
846
847         if [[ -e $FILE_ASOUND_DEVICE ]];then
848                 B_ASOUND_DEVICE_FILE='true'
849         fi
850
851         if [[ -e $FILE_ASOUND_VERSION ]];then
852                 B_ASOUND_VERSION_FILE='true'
853         fi
854
855         if [[ -f $FILE_LSB_RELEASE ]];then
856                 B_LSB_FILE='true'
857         fi
858         
859         if [[ -f $FILE_OS_RELEASE ]];then
860                 B_OS_RELEASE_FILE='true'
861         fi
862
863         if [[ -e $FILE_SCSI ]];then
864                 B_SCSI_FILE='true'
865         fi
866
867         if [[ -n $DISPLAY ]];then
868                 B_SHOW_DISPLAY_DATA='true'
869                 B_RUNNING_IN_DISPLAY='true'
870         fi
871         
872         if [[ -e $FILE_MDSTAT ]];then
873                 B_MDSTAT_FILE='true'
874         fi
875
876         if [[ -e $FILE_MODULES ]];then
877                 B_MODULES_FILE='true'
878         fi
879
880         if [[ -e $FILE_MOUNTS ]];then
881                 B_MOUNTS_FILE='true'
882         fi
883
884         if [[ -e $FILE_PARTITIONS ]];then
885                 B_PARTITIONS_FILE='true'
886         fi
887         # default to the normal location, then search for it
888         if [[ -e $FILE_XORG_LOG ]];then
889                 B_XORG_LOG='true'
890         else
891                 # Detect location of the Xorg log file
892                 if [[ -n $( type -p xset ) ]]; then
893                         FILE_XORG_LOG=$( xset q 2>/dev/null | grep -i 'Log file' | gawk '{print $3}')
894                         if [[ -e $FILE_XORG_LOG ]];then
895                                 B_XORG_LOG='true'
896                         fi
897                 fi
898         fi
899         # gfx output will require this flag
900         if [[ $( whoami ) == 'root' ]];then
901                 B_ROOT='true'
902         fi
903         eval $LOGFE
904 }
905
906 # arg: $1 - version number: main/patch/date
907 parse_version_data()
908 {
909         local version_data=''
910
911         # note, using ####[[:space:]]+ to avoid having this function also trip the version datas
912         case $1 in
913                 date)
914                         version_data="$( gawk -F ': ' '
915                         /####[[:space:]]+Date:/ {
916                                 print $NF
917                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
918                         ;;
919                 main)
920                         version_data="$( gawk '
921                         /####[[:space:]]+Version:/ {
922                                 print $3
923                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
924                         ;;
925                 patch)
926                         version_data="$( gawk '
927                         /####[[:space:]]+Patch Number:/ {
928                                 print $4
929                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
930                         ;;
931         esac
932         echo $version_data
933 }
934
935 initialize_paths()
936 {
937         local path='' added_path='' b_path_found='' sys_path=''
938         # Extra path variable to make execute failures less likely, merged below
939         local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
940         
941         # this needs to be set here because various options call the parent initialize function directly.
942         SCRIPT_PATH=$( dirname $0 )
943
944         # Fallback paths put into $extra_paths; This might, among others, help on gentoo.
945         # Now, create a difference of $PATH and $extra_paths and add that to $PATH:
946         IFS=":"
947         for path in $extra_paths
948         do
949                 b_path_found='false'
950                 for sys_path in $PATH
951                 do
952                         if [[ $path == $sys_path ]];then
953                                 b_path_found='true'
954                         fi
955                 done
956                 if [[ $b_path_found == 'false' ]];then
957                         added_path="$added_path:$path"
958                 fi
959         done
960
961         IFS="$ORIGINAL_IFS"
962         PATH="${PATH}${added_path}"
963         ##echo "PATH='$PATH'"
964         ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""'
965 }
966
967 # No args taken.
968 check_recommended_apps()
969 {
970         eval $LOGFS
971         local bash_array_test=( "one" "two" )
972
973         # check for array ability of bash, this is only good for the warning at this time
974         # the boolean could be used later
975         # bash version 2.05b is used in DSL
976         # bash version 3.0 is used in Puppy Linux; it has a known array bug <reference to be placed here>
977         # versions older than 3.1 don't handle arrays
978         # distro's using below 2.05b are unknown, released in 2002
979         if [[ ${bash_array_test[1]} -eq "two" ]];then
980                 B_BASH_ARRAY='true'
981         else
982                 script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output"
983         fi
984         # test for a few apps that bsds may not have after initial tests
985         if [[ -n $( type -p lspci ) ]];then
986                 B_LSPCI='true'
987         fi
988         if [[ -n $BSD_TYPE ]];then
989                 if [[ -n $( type -p sysctl ) ]];then
990                         B_SYSCTL='true'
991                 fi
992                 if [[ -n $( type -p pciconf ) ]];then
993                         B_PCICONF='true'
994                 fi
995         fi
996         # now setting qdbus/dcop for first run, some systems can have both by the way
997         if [[ -n $( type -p qdbus ) ]];then
998                 B_QDBUS='true'
999         fi
1000         if [[ -n $( type -p dcop ) ]];then
1001                 B_DCOP='true'
1002         fi
1003         eval $LOGFE
1004 }
1005
1006 # Determine if any of the absolutely necessary tools are absent
1007 # No args taken.
1008 check_required_apps()
1009 {
1010         eval $LOGFS
1011         local app_name='' app_path=''
1012         # bc removed from deps for now
1013         local depends="df gawk grep ps readlink tr uname uptime wc"
1014         
1015         if [[ -z $BSD_TYPE  ]];then
1016                 depends="$depends lspci"
1017         elif [[ $BSD_TYPE == 'bsd' ]];then
1018                 depends="$depends sysctl"
1019                 # debian-bsd has lspci but you must be root to run it
1020         elif [[ $BSD_TYPE == 'debian-bsd' ]];then
1021                 depends="$depends sysctl lspci"
1022         fi
1023         # no need to add xprop because it will just give N/A if not there, but if we expand use of xprop,
1024         # should add that here as a test, then use the B_SHOW_DISPLAY_DATA flag to trigger the tests in de function
1025         local x_apps="xrandr xdpyinfo glxinfo" 
1026
1027         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
1028                 for app_name in $x_apps
1029                 do
1030                         app_path=$( type -p $app_name )
1031                         if [[ -z $app_path ]];then
1032                                 script_debugger "Resuming in non X mode: $app_name not found. For package install advice run: $SCRIPT_NAME --recommends"
1033                                 B_SHOW_DISPLAY_DATA='false'
1034                                 break
1035                         fi
1036                 done
1037         fi
1038
1039         app_name=''
1040
1041         for app_name in $depends
1042         do
1043                 app_path=$( type -p $app_name )
1044                 if [[ -z $app_path ]];then
1045                         error_handler 5 "$app_name"
1046                 fi
1047         done
1048         eval $LOGFE
1049 }
1050
1051 ## note: this is now running inside each gawk sequence directly to avoid exiting gawk
1052 ## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array
1053 ## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods
1054 # Enforce boilerplate and buzzword filters
1055 # args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize
1056 sanitize_characters()
1057 {
1058         eval $LOGFS
1059         # Cannot use strong quotes to unquote a string with pipes in it!
1060         # bash will interpret the |'s as usual and try to run a subshell!
1061         # Using weak quotes instead, or use '"..."'
1062         echo "$2" | gawk "
1063         BEGIN {
1064                 IGNORECASE=1
1065         }
1066         {
1067                 gsub(/${!1}/,\"\")
1068                 gsub(/ [ ]+/,\" \")    ## ([ ]+) with (space)
1069                 gsub(/^ +| +$/,\"\")   ## (pipe char) with (nothing)
1070                 print                  ## prints (returns) cleaned input
1071         }"
1072         eval $LOGFE
1073 }
1074
1075 # Set the colorscheme
1076 # args: $1 = <scheme number>|<"none">
1077 set_color_scheme()
1078 {
1079         eval $LOGFS
1080         local i='' a_output_colors='' a_color_codes=''
1081
1082         if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then
1083                 set -- 1
1084         fi
1085         # Set a global variable to allow checking for chosen scheme later
1086         SCHEME="$1"
1087         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1088                 a_color_codes=( $ANSI_COLORS )
1089         else
1090                 a_color_codes=( $IRC_COLORS )
1091         fi
1092         for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ ))
1093         do
1094                 eval "${A_COLORS_AVAILABLE[i]}=\"${a_color_codes[i]}\""
1095         done
1096         IFS=","
1097         a_output_colors=( ${A_COLOR_SCHEMES[$1]} )
1098         IFS="$ORIGINAL_IFS"
1099         # then assign the colors globally
1100         C1="${!a_output_colors[0]}"
1101         C2="${!a_output_colors[1]}"
1102         CN="${!a_output_colors[2]}"
1103         # ((COLOR_SCHEME++)) ## note: why is this? ##
1104         eval $LOGFE
1105 }
1106
1107 select_default_color_scheme()
1108 {
1109         eval $LOGFS
1110         local spacer='  ' options='' user_selection='' config_variable=''
1111         local config_file="$HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf"
1112         local irc_clear="\e[0m" 
1113         local irc_gui='Unset' irc_console='Unset' irc_x_term='Unset'
1114         local console='Unset' virt_term='Unset' global='Unset' 
1115         
1116         if [[ -n $IRC_COLOR_SCHEME ]];then
1117                 irc_gui="Set: $IRC_COLOR_SCHEME"
1118         fi
1119         if [[ -n $IRC_CONS_COLOR_SCHEME ]];then
1120                 irc_console="Set: $IRC_CONS_COLOR_SCHEME"
1121         fi
1122         if [[ -n $IRC_X_TERM_COLOR_SCHEME ]];then
1123                 irc_x_term="Set: $IRC_X_TERM_COLOR_SCHEME"
1124         fi
1125         if [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1126                 virt_term="Set: $VIRT_TERM_COLOR_SCHEME"
1127         fi
1128         if [[ -n $CONSOLE_COLOR_SCHEME ]];then
1129                 console="Set: $CONSOLE_COLOR_SCHEME"
1130         fi
1131         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
1132                 global="Set: $GLOBAL_COLOR_SCHEME"
1133         fi
1134         
1135         # don't want these printing in irc since they show literally
1136         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1137                 irc_clear=''
1138         fi
1139         # first make output neutral so it's just plain default for console client
1140         set_color_scheme "0"
1141         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1142                 print_screen_output "Welcome to $SCRIPT_NAME! Please select the default $COLOR_SELECTION color scheme."
1143                 # print_screen_output "You will see this message only one time per user account, unless you set preferences in: /etc/$SCRIPT_NAME.conf"
1144                 print_screen_output " "
1145         fi
1146         print_screen_output "Because there is no way to know your $COLOR_SELECTION foreground/background colors, you can"
1147         print_screen_output "set your color preferences from color scheme option list below. 0 is no colors, 1 neutral."
1148         print_screen_output "After these, there are 3 sets: 1-dark or light backgrounds; 2-light backgrounds; 3-dark backgrounds."
1149         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1150                 print_screen_output "Please note that this will set the $COLOR_SELECTION preferences only for user: $(whoami)"
1151         fi
1152         print_screen_output "------------------------------------------------------------------------------"
1153         for (( i=0; i < ${#A_COLOR_SCHEMES[@]}; i++ ))
1154         do
1155                 if [[ $i -gt 9 ]];then
1156                         spacer=' '
1157                 fi
1158                 # only offer the safe universal defaults
1159                 case $COLOR_SELECTION in
1160                         global|irc|irc-console|irc-virtual-terminal)
1161                                 if [[ $i -gt $SAFE_COLOR_COUNT ]];then
1162                                         break
1163                                 fi
1164                                 ;;
1165                 esac
1166                 set_color_scheme $i
1167                 print_screen_output "$irc_clear $i)$spacer${C1}Card:${C2} nVidia G86 [GeForce 8400 GS] ${C1}X.Org${C2} 1.7.7"
1168         done
1169         set_color_scheme 0
1170         
1171         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1172                 echo -n "\e[0m"
1173                 print_screen_output "$irc_clear $i)${spacer}Remove all color settings. Restore $SCRIPT_NAME default."
1174                 print_screen_output "$irc_clear $(($i+1)))${spacer}Continue, no changes or config file setting."
1175                 print_screen_output "$irc_clear $(($i+2)))${spacer}Exit, use another terminal, or set manually."
1176                 print_screen_output "------------------------------------------------------------------------------"
1177                 print_screen_output "Simply type the number for the color scheme that looks best to your eyes for your $COLOR_SELECTION settings"
1178                 print_screen_output "and hit ENTER. NOTE: You can bring this option list up by starting $SCRIPT_NAME with option: -c plus one of these numbers:"
1179                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1180                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1181                 print_screen_output "Your selection(s) will be stored here: $config_file"
1182                 print_screen_output "Global overrides all individual color schemes. Individual schemes remove the global setting."
1183                 print_screen_output "------------------------------------------------------------------------------"
1184                 read user_selection
1185                 if [[ -n $( grep -Es '^([0-9]+)$' <<< "$user_selection" ) && $user_selection -lt $i ]];then
1186                         case $COLOR_SELECTION in
1187                                 irc)
1188                                         config_variable='IRC_COLOR_SCHEME'
1189                                         ;;
1190                                 irc-console)
1191                                         config_variable='IRC_CONS_COLOR_SCHEME'
1192                                         ;;
1193                                 irc-virtual-terminal)
1194                                         config_variable='IRC_X_TERM_COLOR_SCHEME'
1195                                         ;;
1196                                 console)
1197                                         config_variable='CONSOLE_COLOR_SCHEME'
1198                                         ;;
1199                                 virtual-terminal)
1200                                         config_variable='VIRT_TERM_COLOR_SCHEME'
1201                                         ;;
1202                                 global)
1203                                         config_variable='GLOBAL_COLOR_SCHEME'
1204                                         ;;
1205                         esac
1206                         set_color_scheme $user_selection
1207                         # make file/directory first if missing
1208                         if [[ ! -f $config_file ]];then
1209                                 if [[ ! -d $HOME/.$SCRIPT_NAME ]];then
1210                                         mkdir $HOME/.$SCRIPT_NAME
1211                                 fi
1212                                 touch $config_file
1213                         fi
1214                         if [[ -z $( grep -s "$config_variable=" $config_file ) ]];then
1215                                 print_screen_output "Creating and updating config file for $COLOR_SELECTION color scheme now..."
1216                                 echo "$config_variable=$user_selection" >> $config_file
1217                         else
1218                                 print_screen_output "Updating config file for $COLOR_SELECTION color scheme now..."
1219                                 sed $SED_I "s/$config_variable=.*/$config_variable=$user_selection/" $config_file
1220                         fi
1221                         # file exists now so we can go on to cleanup
1222                         case $COLOR_SELECTION in
1223                                 irc|irc-console|irc-virtual-terminal|console|virtual-terminal)
1224                                         sed $SED_I '/GLOBAL_COLOR_SCHEME=/d' $config_file
1225                                         ;;
1226                                 global)
1227                                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' -e '/IRC_COLOR_SCHEME=/d' \
1228                                         -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1229                                         ;;
1230                         esac
1231                 elif [[ $user_selection == $i ]];then
1232                         print_screen_output "Removing all color settings from config file now..."
1233                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/GLOBAL_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' \
1234                         -e '/IRC_COLOR_SCHEME=/d' -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1235                         set_color_scheme $DEFAULT_COLOR_SCHEME
1236                 elif [[ $user_selection == $(( $i+1 )) ]];then
1237                         print_screen_output "Ok, continuing $SCRIPT_NAME unchanged. You can set the colors anytime by starting with: -c 95 to 99"
1238                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
1239                                 set_color_scheme $CONSOLE_COLOR_SCHEME
1240                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1241                                 set_color_scheme $VIRT_TERM_COLOR_SCHEME
1242                         else
1243                                 set_color_scheme $DEFAULT_COLOR_SCHEME
1244                         fi
1245                 elif [[ $user_selection == $(( $i+2 )) ]];then
1246                         set_color_scheme $DEFAULT_COLOR_SCHEME
1247                         print_screen_output "Ok, exiting $SCRIPT_NAME now. You can set the colors later."
1248                         exit 0
1249                 else
1250                         print_screen_output "Error - Invalid Selection. You entered this: $user_selection"
1251                         print_screen_output " "
1252                         select_default_color_scheme
1253                 fi
1254         else
1255                 print_screen_output "------------------------------------------------------------------------------"
1256                 print_screen_output "After finding the scheme number you like, simply run this again in a terminal to set the configuration"
1257                 print_screen_output "data file for your irc client. You can set color schemes for the following: start inxi with -c plus:"
1258                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1259                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1260                 exit 0
1261         fi
1262
1263         eval $LOGFE
1264 }
1265
1266 ########################################################################
1267 #### UTILITY FUNCTIONS
1268 ########################################################################
1269
1270 #### -------------------------------------------------------------------
1271 #### error handler, debugger, script updater
1272 #### -------------------------------------------------------------------
1273
1274 # Error handling
1275 # args: $1 - error number; $2 - optional, extra information; $3 - optional extra info
1276 error_handler()
1277 {
1278         eval $LOGFS
1279         local error_message=''
1280
1281         # assemble the error message
1282         case $1 in
1283                 2)      error_message="large flood danger, debug buffer full!"
1284                         ;;
1285                 3)      error_message="unsupported color scheme number: $2"
1286                         ;;
1287                 4)      error_message="unsupported verbosity level: $2"
1288                         ;;
1289                 5)      error_message="dependency not met: $2 not found in path.\nFor distribution installation package names and missing apps information, run: $SCRIPT_NAME --recommends"
1290                         ;;
1291                 6)      error_message="/proc not found! Quitting..."
1292                         ;;
1293                 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"
1294                         ;;
1295                 8)      error_message="the self-updater failed, wget exited with error: $2.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown <user name> $SCRIPT_PATH/$SCRIPT_NAME"
1296                         ;;
1297                 9)      error_message="unsupported debugging level: $2"
1298                         ;;
1299                 10)
1300                         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/"
1301                         ;;
1302                 11)
1303                         error_message="unsupported testing option argument: -! $2"
1304                         ;;
1305                 12)
1306                         error_message="the svn branch download url: $2\nappears to be empty currently. Make sure there is an actual svn branch version\nactive before you try this again. Check http://code.google.com/p/inxi\nto verify the branch status."
1307                         ;;
1308                 13)
1309                         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"
1310                         ;;
1311                 14)
1312                         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"
1313                         ;;
1314                 15)
1315                         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"
1316                         ;;
1317                 16)
1318                         error_message="$SCRIPT_NAME downloaded but the file data is corrupted. Purged data and using current version."
1319                         ;;
1320                 17)
1321                         error_message="All $SCRIPT_NAME self updater features have been disabled by the distribution\npackage maintainer. This includes the option you used: $2"
1322                         ;;
1323                 18)
1324                         error_message="The argument you provided for $2 does not have supported syntax.\nPlease use the following formatting:\n$3"
1325                         ;;
1326                 19)
1327                         error_message="The option $2 has been deprecated. Please use $3 instead.\nSee -h for instructions and syntax."
1328                         ;;
1329                 20)
1330                         error_message="The option you selected has been deprecated. $2\nSee the -h (help) menu for currently supported options."
1331                         ;;
1332                 *)      error_message="error unknown: $@"
1333                         set -- 99
1334                         ;;
1335         esac
1336         # then print it and exit
1337         print_screen_output "Error $1: $error_message"
1338         eval $LOGFE
1339         exit $1
1340 }
1341
1342 # prior to script up set, pack the data into an array
1343 # then we'll print it out later.
1344 # args: $1 - $@ debugging string text
1345 script_debugger()
1346 {
1347         eval $LOGFS
1348         if [[ $B_SCRIPT_UP == 'true' ]];then
1349                 # only return if debugger is off and no pre start up errors have occured
1350                 if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then
1351                         return 0
1352                 # print out the stored debugging information if errors occured
1353                 elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then
1354                         for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ ))
1355                         do
1356                                 print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}"
1357                         done
1358                         DEBUG_BUFFER_INDEX=0
1359                 fi
1360                 # or print out normal debugger messages if debugger is on
1361                 if [[ $DEBUG -gt 0 ]];then
1362                         print_screen_output "$1"
1363                 fi
1364         else
1365                 if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then
1366                         error_handler 2
1367                 # this case stores the data for later printout, will print out only
1368                 # at B_SCRIPT_UP == 'true' if array index > 0
1369                 else
1370                         A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1"
1371                         # increment count for next pre script up debugging error
1372                         (( DEBUG_BUFFER_INDEX++ ))
1373                 fi
1374         fi
1375         eval $LOGFE
1376 }
1377
1378 # NOTE: no logging available until get_parameters is run, since that's what sets logging
1379 # in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables.
1380 # $1 alone: logs data; $2 with or without $3 logs func start/end.
1381 # $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]]
1382 log_function_data()
1383 {
1384         if [ "$B_USE_LOGGING" == 'true' ];then
1385                 local logged_data='' spacer='   ' line='----------------------------------------'
1386                 case $1 in
1387                         fs)
1388                                 logged_data="Function: $2 - Primary: Start"
1389                                 if [ -n "$3" ];then
1390                                         logged_data="$logged_data\n${spacer}Args: $3"
1391                                 fi
1392                                 spacer=''
1393                                 ;;
1394                         fe)
1395                                 logged_data="Function: $2 - Primary: End"
1396                                 spacer=''
1397                                 ;;
1398                         cat)
1399                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1400                                         logged_data="\n$line\nFull file data: cat $2\n\n$( cat $2 )\n$line\n"
1401                                         spacer=''
1402                                 fi
1403                                 ;;
1404                         raw)
1405                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1406                                         logged_data="\n$line\nRaw system data:\n\n$2\n$line\n"
1407                                         spacer=''
1408                                 fi
1409                                 ;;
1410                         *)
1411                                 logged_data="$1"
1412                                 ;;
1413                 esac
1414                 # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2).
1415                 # This pattern doesn't work for irc colors, if we need that someone can figure it out
1416                 if [[ -n $logged_data ]];then
1417                         if [[ $B_LOG_COLORS != 'true' ]];then
1418                                 echo -e "${spacer}$logged_data" | sed $SED_RX 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE
1419                         else
1420                                 echo -e "${spacer}$logged_data" >> $LOG_FILE
1421                         fi
1422                 fi
1423         fi
1424 }
1425
1426 # called in the initial -@ 10 script args setting so we can get logging as soon as possible
1427 # will have max 3 files, inxi.log, inxi.1.log, inxi.2.log
1428 create_rotate_logfiles()
1429 {
1430         if [[ ! -d $SCRIPT_DATA_DIR ]];then
1431                 mkdir $SCRIPT_DATA_DIR
1432         fi
1433         # do the rotation if logfile exists
1434         if [[ -f $LOG_FILE ]];then
1435                 # copy if present second to third
1436                 if [[ -f $LOG_FILE_1 ]];then
1437                         mv -f $LOG_FILE_1 $LOG_FILE_2
1438                 fi
1439                 # then copy initial to second
1440                 mv -f $LOG_FILE $LOG_FILE_1
1441         fi
1442         # now create the logfile
1443         touch $LOG_FILE
1444         # and echo the start data
1445         echo "=========================================================" >> $LOG_FILE
1446         echo "START $SCRIPT_NAME LOGGING:"                               >> $LOG_FILE
1447         echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )"              >> $LOG_FILE
1448         echo "=========================================================" >> $LOG_FILE
1449 }
1450
1451 # args: $1 - download url, not including file name; $2 - string to print out
1452 # $3 - update type option
1453 # note that $1 must end in / to properly construct the url path
1454 script_self_updater()
1455 {
1456         eval $LOGFS
1457         local wget_error=0 file_contents='' wget_man_error=0 
1458         local man_file_path="$MAN_FILE_LOCATION/inxi.1.gz"
1459         
1460         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1461                 print_screen_output "Sorry, you can't run the $SCRIPT_NAME self updater option (-$3) in an IRC client."
1462                 exit 1
1463         fi
1464
1465         print_screen_output "Starting $SCRIPT_NAME self updater."
1466         print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER"
1467         print_screen_output "Current version patch number: $SCRIPT_PATCH_NUMBER"
1468         print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..."
1469
1470         file_contents="$( wget -q -O - $1$SCRIPT_NAME )" || wget_error=$?
1471         # then do the actual download
1472         if [[  $wget_error -eq 0 ]];then
1473                 # make sure the whole file got downloaded and is in the variable
1474                 if [[ -n $( grep '###\*\*EOF\*\*###' <<< "$file_contents" ) ]];then
1475                         echo "$file_contents" > $SCRIPT_PATH/$SCRIPT_NAME || error_handler 14 "$?"
1476                         chmod +x $SCRIPT_PATH/$SCRIPT_NAME || error_handler 15 "$?"
1477                         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
1478                         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
1479                         print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER"
1480                         print_screen_output "New $2 version patch number: $SCRIPT_PATCH_NUMBER"
1481                         print_screen_output "To run the new version, just start $SCRIPT_NAME again."
1482                         print_screen_output "----------------------------------------"
1483                         print_screen_output "Starting download of man page file now."
1484                         if [[ ! -d $MAN_FILE_LOCATION ]];then
1485                                 print_screen_output "The required man directory was not detected on your system, unable to continue: $MAN_FILE_LOCATION"
1486                         else
1487                                 if [[ $B_ROOT == 'true' ]];then
1488                                         print_screen_output "Checking Man page download URL..."
1489                                         if [[ -f /usr/share/man/man8/inxi.8.gz ]];then
1490                                                 print_screen_output "Updating man page location to man1."
1491                                                 mv -f /usr/share/man/man8/inxi.8.gz /usr/share/man/man1/inxi.1.gz 
1492                                                 if [[ -n $( type -p mandb ) ]];then
1493                                                         exec $( type -p mandb ) -q 
1494                                                 fi
1495                                         fi
1496                                         wget -q --spider $MAN_FILE_DOWNLOAD || wget_man_error=$?
1497                                         if [[ $wget_man_error -eq 0 ]];then
1498                                                 print_screen_output "Man file download URL verified: $MAN_FILE_DOWNLOAD"
1499                                                 print_screen_output "Downloading Man page file now."
1500                                                 wget -q -O $man_file_path $MAN_FILE_DOWNLOAD || wget_man_error=$?
1501                                                 if [[ $wget_man_error -gt 0 ]];then
1502                                                         print_screen_output "Oh no! Something went wrong downloading the Man gz file at: $MAN_FILE_DOWNLOAD"
1503                                                         print_screen_output "Check the error messages for what happened. Error: $wget_man_error"
1504                                                 else
1505                                                         print_screen_output "Download/install of man page successful. Check to make sure it works: man inxi"
1506                                                 fi
1507                                         else
1508                                                 print_screen_output "Man file download URL failed, unable to continue: $MAN_FILE_DOWNLOAD"
1509                                         fi
1510                                 else
1511                                         print_screen_output "Updating / Installing the Man page requires root user, writing to: $MAN_FILE_LOCATION"
1512                                         print_screen_output "If you want the man page, you'll have to run $SCRIPT_NAME -$3 as root."
1513                                 fi
1514                         fi
1515                         exit 0
1516                 else
1517                         error_handler 16
1518                 fi
1519         # now run the error handlers on any wget failure
1520         else
1521                 if [[ $2 == 'svn server' ]];then
1522                         error_handler 8 "$wget_error"
1523                 elif [[ $2 == 'alt server' ]];then
1524                         error_handler 10 "$1"
1525                 else
1526                         error_handler 12 "$1"
1527                 fi
1528         fi
1529         eval $LOGFS
1530 }
1531
1532 # args: $1 - debug data type: sys|xorg|disk
1533 debug_data_collector()
1534 {
1535         local xiin_app='' xiin_data_file='' xiin_download='' error='' b_run_xiin='false'
1536         local debug_data_dir='' bsd_string=''
1537         local completed_gz_file='' xiin_file='xiin.py' ftp_upload='ftp.techpatterns.com/incoming'
1538         local Line='-------------------------'
1539         local start_directory=$( pwd )
1540         
1541         if [[ -n $BSD_TYPE ]];then
1542                 bsd_string="$BSD_TYPE-"
1543         fi
1544         
1545         debug_data_dir="inxi-$bsd_string$(tr ' ' '-' <<< $HOSTNAME | tr '[A-Z]' '[a-z]' )-$1-$(date +%Y%m%d)" 
1546         
1547         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1548                 if [[ -n $ALTERNATE_FTP ]];then
1549                         ftp_upload=$ALTERNATE_FTP
1550                 fi
1551                 echo "Starting debugging data collection type: $1"
1552                 echo -n "Checking/creating required directories... "
1553                 if [[ ! -d $SCRIPT_DATA_DIR ]];then
1554                         mkdir $SCRIPT_DATA_DIR
1555                 fi
1556                 echo 'completed'
1557                 cd $SCRIPT_DATA_DIR
1558                 if [[ -d $SCRIPT_DATA_DIR/$debug_data_dir ]];then
1559                         echo 'Deleting previous xiin data directory...'
1560                         rm -rf $SCRIPT_DATA_DIR/$debug_data_dir
1561                 fi
1562                 mkdir $SCRIPT_DATA_DIR/$debug_data_dir
1563                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
1564                         echo 'Deleting previous tar.gz file...'
1565                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1566                 fi
1567                 
1568                 echo 'Collecting system info: sensors, lsusb, lspci, lspci -v data, plus /proc data'
1569                 echo 'also checking for dmidecode data: note, you must be root to have dmidecode work.'
1570                 echo "Data going into: $SCRIPT_DATA_DIR/$debug_data_dir"
1571                 # bsd tools
1572                 pciconf -vl &> $debug_data_dir/bsd-pciconf-vl.txt
1573                 sysctl -a &> $debug_data_dir/bsd-sysctl-a.txt
1574                 
1575                 dmidecode &> $debug_data_dir/dmidecode.txt
1576                 
1577                 lscpu &> $debug_data_dir/lscpu.txt
1578                 lspci &> $debug_data_dir/lspci.txt
1579                 lspci -n &> $debug_data_dir/lspci-n.txt
1580                 lspci -v &> $debug_data_dir/lspci-v.txt
1581                 lsusb &> $debug_data_dir/lsusb.txt
1582                 ps aux &> $debug_data_dir/ps-aux.txt
1583                 runlevel &> $debug_data_dir/runlevel.txt
1584                 systemctl list-units &> $debug_data_dir/systemctl-list-units.txt
1585                 systemctl list-units --type=target &> $debug_data_dir/systemctl-list-units-target.txt
1586                 initctl list &> $debug_data_dir/initctl-list.txt
1587                 sensors &> $debug_data_dir/sensors.txt
1588                 strings --version  &> $debug_data_dir/strings.txt
1589                 nvidia-smi -q &> $debug_data_dir/nvidia-smi-q.txt
1590                 nvidia-smi -q -x &> $debug_data_dir/nvidia-smi-xq.txt
1591                 
1592                 ls /usr/bin/gcc* &> $debug_data_dir/gcc-sys-versions.txt
1593                 gcc --version &> $debug_data_dir/gcc-version.txt
1594                 cat /etc/issue &> $debug_data_dir/etc-issue.txt
1595                 cat $FILE_LSB_RELEASE &> $debug_data_dir/lsb-release.txt
1596                 cat $FILE_OS_RELEASE &> $debug_data_dir/os-release.txt
1597                 cat $FILE_ASOUND_DEVICE &> $debug_data_dir/proc-asound-device.txt
1598                 cat $FILE_ASOUND_VERSION &> $debug_data_dir/proc-asound-version.txt
1599                 cat $FILE_CPUINFO &> $debug_data_dir/proc-cpu-info.txt
1600                 cat $FILE_MEMINFO &> $debug_data_dir/proc-meminfo.txt
1601                 cat $FILE_MODULES &> $debug_data_dir/proc-modules.txt
1602                 cat /proc/net/arp &> $debug_data_dir/proc-net-arp.txt 
1603                 # bsd data
1604                 cat /var/run/dmesg.boot &> $debug_data_dir/bsd-var-run-dmesg.boot.txt 
1605                 
1606                 check_recommends_user_output &> $debug_data_dir/check-recommends-user-output.txt
1607                 # first download and verify xiin
1608                 if [[ $B_UPLOAD_DEBUG_DATA == 'true' || $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1609                         touch $SCRIPT_DATA_DIR/$debug_data_dir/xiin-error.txt
1610                         echo "Downloading required tree traverse tool $xiin_file..."
1611                         if [[ -f xiin && ! -f $xiin_file ]];then
1612                                 mv -f xiin $xiin_file
1613                         fi
1614                         # -Nc is creating really weird download anomolies, so using -O instead
1615                         xiin_download="$( wget -q -O - http://inxi.googlecode.com/svn/branches/xiin/$xiin_file )"
1616                         # if nothing got downloaded kick out error, otherwise we'll use an older version
1617                         if [[ $? -gt 0 && ! -f $xiin_file ]];then
1618                                 echo -e "ERROR: Failed to download required file: $xiin_file\nMaybe the remote site is down or your networking is broken?"
1619                                 echo "Continuing with incomplete data collection."
1620                                 echo "$xiin_file download failed and no existing $xiin_file" >> $debug_data_dir/xiin-error.txt
1621                         elif [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) || -f $xiin_file ]];then
1622                                 if [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) ]];then
1623                                         echo "Updating $xiin_file from remote location"
1624                                         echo "$xiin_download" > $xiin_file
1625                                 else
1626                                         echo "Using local $xiin_file due to download failure"
1627                                 fi
1628                                 b_run_xiin='true'
1629                         else
1630                                 echo -e "ERROR: $xiin_file downloaded but the program file data is corrupted.\nContinuing with incomplete data collection."
1631                                 echo "$xiin_file downloaded but the program file data is corrupted." >> $debug_data_dir/xiin-error.txt
1632                         fi
1633                 fi
1634                 # note, only bash 4> supports ;;& for case, so using if/then here
1635                 if [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1636                         xiin_data_file=$SCRIPT_DATA_DIR/$debug_data_dir/xiin-sys.txt
1637                         echo 'Collecting networking data...'
1638                         ifconfig &> $debug_data_dir/ifconfig.txt
1639                         ip addr &> $debug_data_dir/ip-addr.txt
1640                         if [[ $b_run_xiin == 'true' && -z $BSD_TYPE ]];then
1641                                 echo $Line
1642                                 echo "Running $xiin_file tool now on /sys..."
1643                                 echo "Using Python version:" && python --version
1644                                 python --version &> $debug_data_dir/python-version.txt
1645                                 python ./$xiin_file -d /sys -f $xiin_data_file
1646                                 if [[ $? -ne 0 ]];then
1647                                         error=$?
1648                                         echo -e "ERROR: $xiin_file exited with error $error - removing data file.\nContinuing with incomplete data collection."
1649                                         echo "Continuing with incomplete data collection."
1650                                         rm -f $xiin_data_file
1651                                         echo "$xiin_file data generation failed with python error $error" >> $debug_data_dir/xiin-error.txt
1652                                 fi
1653                                 echo $Line
1654                         fi
1655                 fi
1656                 if [[ $1 == 'xorg' || $1 == 'all' ]];then
1657                         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
1658                                 echo 'Warning: only some of the data collection can occur if you are not in X'
1659                                 touch $debug_data_dir/warning-user-not-in-x
1660                         fi
1661                         if [[ $B_ROOT == 'true' ]];then
1662                                 echo 'Warning: only some of the data collection can occur if you are running as Root user'
1663                                 touch $debug_data_dir/warning-root-user
1664                         fi
1665                         echo 'Collecting Xorg log and xorg.conf files'
1666                         if [[ -e $FILE_XORG_LOG ]];then
1667                                 cat $FILE_XORG_LOG &> $debug_data_dir/xorg-log-file.txt
1668                         else
1669                                 touch $debug_data_dir/no-xorg-log-file
1670                         fi
1671                         if [[ -e /etc/X11/xorg.conf ]];then
1672                                 cp /etc/X11/xorg.conf $SCRIPT_DATA_DIR/$debug_data_dir
1673                         else
1674                                 touch $debug_data_dir/no-xorg-conf-file
1675                         fi
1676                         if [[ -n $( ls /etc/X11/xorg.conf.d/ 2>/dev/null ) ]];then
1677                                 ls /etc/X11/xorg.conf.d &> $debug_data_dir/ls-etc-x11-xorg-conf-d.txt
1678                                 cp /etc/X11/xorg.conf.d $SCRIPT_DATA_DIR/$debug_data_dir
1679                         else
1680                                 touch $debug_data_dir/no-xorg-conf-d-files
1681                         fi
1682                         echo 'Collecting X, xprop, glxinfo, xrandr, xdpyinfo data...'
1683                         xprop -root &> $debug_data_dir/xprop_root.txt
1684                         glxinfo &> $debug_data_dir/glxinfo.txt
1685                         xdpyinfo &> $debug_data_dir/xdpyinfo.txt
1686                         xrandr &> $debug_data_dir/xrandr.txt
1687                         X -version &> $debug_data_dir/x-version.txt
1688                         Xorg -version &> $debug_data_dir/xorg-version.txt
1689                         echo $GNOME_DESKTOP_SESSION_ID &> $debug_data_dir/gnome-desktop-session-id.txt
1690                         # kde 3 id
1691                         echo $KDE_FULL_SESSION &> $debug_data_dir/kde3-ful-session.txt
1692                         echo $KDE_SESSION_VERSION &> $debug_data_dir/kde456-session-version.txt
1693                         echo "$(kded$KDE_SESSION_VERSION --version )" &> $debug_data_dir/kde-version-data.txt
1694                         echo $XDG_CURRENT_DESKTOP &> $debug_data_dir/xdg-current-desktop.txt
1695                 fi
1696                 if [[ $1 == 'disk' || $1 == 'all' ]];then
1697                         echo 'Collecting dev, label, disk, uuid data, df...'
1698                         ls -l /dev &> $debug_data_dir/dev-data.txt
1699                         ls -l /dev/disk &> $debug_data_dir/dev-disk-data.txt
1700                         ls -l /dev/disk/by-id &> $debug_data_dir/dev-disk-id-data.txt
1701                         ls -l /dev/disk/by-label &> $debug_data_dir/dev-disk-label-data.txt
1702                         ls -l /dev/disk/by-uuid &> $debug_data_dir/dev-disk-uuid-data.txt
1703                         ls -l /dev/disk/by-path &> $debug_data_dir/dev-disk-path-data.txt
1704                         ls -l /dev/mapper &> $debug_data_dir/dev-disk-mapper-data.txt
1705                         readlink /dev/root &> $debug_data_dir/dev-root.txt
1706                         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
1707                         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
1708                         df -H -T &> $debug_data_dir/bsd-df-H-T-no-excludes.txt
1709                         df -H &> $debug_data_dir/bsd-df-H-no-excludes.txt
1710                         # bsd tool
1711                         mount &> $debug_data_dir/mount.txt
1712                         gpart list &> $debug_data_dir/bsd-gpart-list.txt
1713                         gpart show &> $debug_data_dir/bsd-gpart-show.txt
1714                         gpart status &> $debug_data_dir/bsd-gpart-status.txt
1715                         swapctl -l &> $debug_data_dir/bsd-swapctl-l.txt
1716                         swapon -s &> $debug_data_dir/swapon-s.txt
1717                         sysctl -b kern.geom.conftxt  &> $debug_data_dir/bsd-sysctl-b-kern.geom.conftxt.txt
1718                         sysctl -b kern.geom.confxml &> $debug_data_dir/bsd-sysctl-b-kern.geom.confxml.txt
1719                         zfs list &> $debug_data_dir/bsd-zfs-list.txt
1720                         zpool list &> $debug_data_dir/bsd-zpool-list.txt
1721                         zpool list -v &> $debug_data_dir/bsd-zpool-list-v.txt
1722                         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
1723                         df -P &> $debug_data_dir/bsd-df-P-no-excludes.txt
1724                         cat /proc/mdstat &> $debug_data_dir/proc-mdstat.txt
1725                         cat $FILE_PARTITIONS &> $debug_data_dir/proc-partitions.txt
1726                         cat $FILE_SCSI &> $debug_data_dir/proc-scsi.txt
1727                         cat $FILE_MOUNTS &> $debug_data_dir/proc-mounts.txt
1728                         cat /proc/sys/dev/cdrom/info &> $debug_data_dir/proc-cdrom-info.txt
1729                         ls /proc/ide/ &> $debug_data_dir/proc-ide.txt
1730                         cat /proc/ide/*/* &> $debug_data_dir/proc-ide-hdx-cat.txt
1731                         cat /etc/fstab &> $debug_data_dir/etc-fstab.txt
1732                         cat /etc/mtab &> $debug_data_dir/etc-mtab.txt
1733                 fi
1734                 echo 'Creating inxi output file now. This can take a few seconds...'
1735                 echo "Starting $SCRIPT_NAME from: $start_directory"
1736                 cd $start_directory
1737                 $SCRIPT_PATH/$SCRIPT_NAME -FRploudxxx -c 0 -@ 8 > $SCRIPT_DATA_DIR/$debug_data_dir/inxi-FRploudxxx.txt
1738                 cp $LOG_FILE $SCRIPT_DATA_DIR/$debug_data_dir
1739                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
1740                         echo "Found and removing previous tar.gz data file: $debug_data_dir.tar.gz"
1741                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1742                 fi
1743                 cd $SCRIPT_DATA_DIR
1744                 echo 'Creating tar.gz compressed file of this material now. Contents:'
1745                 echo $Line
1746                 tar -cvzf $debug_data_dir.tar.gz $debug_data_dir
1747                 echo $Line
1748                 echo 'Cleaning up leftovers...'
1749                 rm -rf $debug_data_dir
1750                 echo 'Testing gzip file integrity...'
1751                 gzip -t $debug_data_dir.tar.gz
1752                 if [[ $? -gt 0 ]];then
1753                         echo 'Data in gz is corrupted, removing gzip file, try running data collector again.'
1754                         rm -f $debug_data_dir.tar.gz
1755                         echo "Data in gz is corrupted, removed gzip file" >> $debug_data_dir/gzip-error.txt
1756                 else
1757                         echo 'All done, you can find your data gzipped directory here:'
1758                         completed_gz_file=$SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1759                         echo $completed_gz_file
1760                         if [[ $B_UPLOAD_DEBUG_DATA == 'true' ]];then
1761                                 echo $Line
1762                                 if [[ $b_run_xiin == 'true' ]];then
1763                                         echo "Running automatic upload of data to remote server $ftp_upload now..."
1764                                         python ./$xiin_file --version
1765                                         python ./$xiin_file -u $completed_gz_file $ftp_upload
1766                                         if [[ $? -gt 0 ]];then
1767                                                 echo $Line
1768                                                 echo "Error: looks like the ftp upload failed. Error number: $?"
1769                                                 echo "The ftp upload failed. Error number: $?" >> $debug_data_dir/xiin-error.txt
1770                                         fi
1771                                 else
1772                                         echo 'Unable to run the automoatic ftp upload because of an error with the xiin download.'
1773                                         echo "Unable to run the automoatic ftp upload because of an error with the xiin download" >> $debug_data_dir/xiin-error.txt
1774                                 fi
1775                         else
1776                                 echo 'You can upload this here using most file managers: ftp.techpatterns.com/incoming'
1777                                 echo 'then let a maintainer know it is uploaded.'
1778                         fi
1779                 fi
1780         else
1781                 echo 'This feature only available in console or shell client! Exiting now.'
1782         fi
1783         exit 0
1784 }
1785
1786 check_recommends_user_output()
1787 {
1788         local Line='-----------------------------------------------------------------------------------------'
1789         local gawk_version='N/A' sed_version='N/A' sudo_version='N/A' python_version='N/A'
1790         
1791         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1792                 print_screen_output "Sorry, you can't run this option in an IRC client."
1793                 exit 1
1794         fi
1795         
1796         initialize_paths
1797         
1798         echo "$SCRIPT_NAME will now begin checking for the programs it needs to operate. First a check of"
1799         echo "the main languages and tools $SCRIPT_NAME uses. Python is only for debugging data collection."
1800         echo $Line
1801         echo "Bash version: $( bash --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU bash/ {print $4}' )"
1802         if [[ -n $( type -p gawk ) ]];then
1803                 gawk_version=$( gawk --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU Awk/ {print $3}' )
1804         fi
1805         if [[ -n $( type -p sed ) ]];then
1806                 sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU sed version/ {print $4}' )
1807                 if [[ -z $sed_version ]];then
1808                         # note: bsd sed shows error with --version flag
1809                         sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^sed: illegal option/ {print "BSD sed"}' )
1810                 fi
1811         fi
1812         if [[ -n $( type -p sudo ) ]];then
1813                 sudo_version=$( sudo -V 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Sudo version/ {print $3}' )
1814         fi
1815         if [[ -n $( type -p python ) ]];then
1816                 python_version=$( python --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Python/ {print $2}' )
1817         fi
1818         echo "Gawk version: $gawk_version"
1819         echo "Sed version: $sed_version"
1820         echo "Sudo version: $sudo_version"
1821         echo "Python version: $python_version"
1822         echo $Line
1823         echo "Test One: Required System Directories."
1824         echo "If one of these system directories is missing, $SCRIPT_NAME cannot operate:"
1825         echo 
1826         check_recommends_items 'required-dirs'
1827         echo "Test Two: Required Core Applications."
1828         echo "If one of these applications is missing, $SCRIPT_NAME cannot operate:"
1829         echo 
1830         check_recommends_items 'required-apps'
1831         echo 'Test Three: Script Recommends for Graphics Features. If you do not use X these do not matter.'
1832         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1833         echo 
1834         check_recommends_items 'recommended-x-apps'
1835         echo 'Test Four: Script Recommends for Remaining Features.' 
1836         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1837         echo 
1838         check_recommends_items 'recommended-apps'
1839         echo 'Test Five: System Directories for Various Information.' 
1840         echo "If one of these directories is missing, $SCRIPT_NAME will have incomplete output:"
1841         echo 
1842         check_recommends_items 'system-dirs'
1843         echo 'All tests completed.' 
1844 }
1845 # args: $1 - check item
1846 check_recommends_items()
1847 {
1848         local item='' item_list='' item_string='' missing_items='' missing_string=''
1849         local package='' application='' feature='' type='' starter='' finisher=''
1850         local package_deb='' package_pacman='' package_rpm='' 
1851         local print_string='' separator=''
1852         local required_dirs='/proc /sys'
1853         # package-owner: 1 - debian/ubuntu; 2 - arch; 3 - yum/rpm
1854         # pardus: pisi sf -q /usr/bin/package
1855         local required_apps='
1856         df:coreutils~coreutils~coreutils~:partition_data 
1857         gawk:gawk~gawk~gawk~:core_tool
1858         grep:grep~grep~grep~:string_search 
1859         lspci:pciutils~pciutils~pciutils~:hardware_data 
1860         ps:procps~procps~procps~:process_data 
1861         readlink:coreutils~coreutils~coreutils~: 
1862         sed:sed~sed~sed~:string_replace 
1863         tr:coreutils~coreutils~coreutils~:character_replace 
1864         uname:uname~coreutils~coreutils~:kernel_data 
1865         uptime:procps~procps~procps~: 
1866         wc:coreutils~coreutils~coreutils~:word_character_count
1867         '
1868         local x_recommends='
1869         glxinfo:mesa-utils~mesa-demos~glx-utils_(openSUSE_12.3_and_later_Mesa-demo-x)~:-G_glx_info 
1870         xdpyinfo:X11-utils~xorg-xdpyinfo~xorg-x11-utils~:-G_multi_screen_resolution 
1871         xprop:X11-utils~xorg-xprop~x11-utils~:-S_desktop_data 
1872         xrandr:x11-xserver-utils~xrandr~x11-server-utils~:-G_single_screen_resolution
1873         '
1874         local recommended_apps='
1875         dmidecode:dmidecode~dmidecode~dmidecode~:-M_if_no_sys_machine_data 
1876         file:file~file~file~:-o_unmounted_file_system
1877         hddtemp:hddtemp~hddtemp~hddtemp~:-Dx_show_hdd_temp 
1878         ifconfig:net-tools~net-tools~net-tools~:-i_ip_lan-deprecated
1879         ip:iproute~iproute2~iproute~:-i_ip_lan
1880         sensors:lm-sensors~lm_sensors~lm-sensors~:-s_sensors_output
1881         strings:binutils~~~:-I_sysvinit_version
1882         lsusb:usbutils~usbutils~usbutils~:-A_usb_audio;-N_usb_networking 
1883         modinfo:module-init-tools~module-init-tools~module-init-tools~:-Ax,-Nx_module_version 
1884         runlevel:sysvinit~sysvinit~systemd~:-I_runlevel
1885         sudo:sudo~sudo~sudo~:-Dx_hddtemp-user;-o_file-user
1886         '
1887         local recommended_dirs='
1888         /sys/class/dmi/id:-M_system,_motherboard,_bios
1889         /dev:-l,-u,-o,-p,-P,-D_disk_partition_data
1890         /dev/disk/by-label:-l,-o,-p,-P_partition_labels
1891         /dev/disk/by-uuid:-u,-o,-p,-P_partition_uuid
1892         /var/run/dmesg.boot:-C,-f_(BSD_only)
1893         '
1894         
1895         case $1 in
1896                 required-dirs)
1897                         item_list=$required_dirs
1898                         item_string='Required file system'
1899                         missing_string='system directories'
1900                         type='directories'
1901                         ;;
1902                 required-apps)
1903                         item_list=$required_apps
1904                         item_string='Required application'
1905                         missing_string='applications, and their corresponding packages,'
1906                         type='applications'
1907                         ;;
1908                 recommended-x-apps)
1909                         item_list=$x_recommends
1910                         item_string='Recommended X application'
1911                         missing_string='applications, and their corresponding packages,'
1912                         type='applications'
1913                         ;;
1914                 recommended-apps)
1915                         item_list=$recommended_apps
1916                         item_string='Recommended application'
1917                         missing_string='applications, and their corresponding packages,'
1918                         type='applications'
1919                         ;;
1920                 system-dirs)
1921                         item_list=$recommended_dirs
1922                         item_string='System directory'
1923                         missing_string='system directories'
1924                         type='directories'
1925                         ;;
1926         esac
1927         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
1928         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
1929         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
1930         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
1931         
1932         for item in $item_list
1933         do
1934                 if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 0 ]];then
1935                         application=$item
1936                         package=''
1937                         feature=''
1938                         location=''
1939                 elif [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 1 ]];then
1940                         application=$( cut -d ':' -f 1 <<< $item )
1941                         package=''
1942                         feature=$( cut -d ':' -f 2 <<< $item )
1943                         location=''
1944                 else
1945                         application=$( cut -d ':' -f 1 <<< $item )
1946                         package=$( cut -d ':' -f 2 <<< $item )
1947                         location=$( type -p $application )
1948                         if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 2 ]];then
1949                                 feature=$( cut -d ':' -f 3 <<< $item )
1950                         else
1951                                 feature=''
1952                         fi
1953                 fi
1954                 if [[ -n $feature ]];then
1955                         print_string="$item_string: $application (info: $( sed 's/_/ /g' <<< $feature ))"
1956                 else
1957                         print_string="$item_string: $application"
1958                 fi
1959                 
1960                 starter="$( sed -e :a -e 's/^.\{1,75\}$/&./;ta' <<< $print_string )"
1961                 if [[ -z $( grep '^/' <<< $application ) && -n $location ]] || [[ -d $application ]];then
1962                         if [[ -n $location ]];then
1963                                 finisher=" $location"
1964                         else
1965                                 finisher=" Present"
1966                         fi
1967                 else
1968                         finisher=" Missing"
1969                         missing_items="$missing_items$separator$application:$package"
1970                         separator=' '
1971                 fi
1972                 
1973                 echo "$starter$finisher"
1974         done
1975         echo 
1976         if [[ -n $missing_items ]];then
1977                 echo "The following $type are missing from your system:"
1978                 for item in $missing_items
1979                 do
1980                         application=$( cut -d ':' -f 1 <<< $item )
1981                         if [[ $type == 'applications' ]];then
1982                                 # echo '--------------------------------------------------------'
1983                                 echo
1984                                 package=$( cut -d ':' -f 2 <<< $item )
1985                                 package_deb=$( cut -d '~' -f 1 <<< $package )
1986                                 package_pacman=$( cut -d '~' -f 2 <<< $package )
1987                                 package_rpm=$( cut -d '~' -f 3 <<< $package )
1988                                 echo "Application: $application"
1989                                 echo "To add to your system, install the proper distribution package for your system:"
1990                                 echo "Debian/Ubuntu: $package_deb :: Arch Linux: $package_pacman :: Redhat/Fedora/Suse: $package_rpm"
1991                         else
1992                                 echo "Directory: $application"
1993                         fi
1994                 done
1995                 if [[ $item_string == 'System directory' ]];then
1996                         echo "These directories are created by the kernel, so don't worry if they are not present."
1997                 fi
1998         else
1999                 echo "All the $( cut -d ' ' -f 1 <<< $item_string | sed -e 's/Re/re/' -e 's/Sy/sy/' ) $type are present."
2000         fi
2001         echo $Line
2002 }
2003
2004 #### -------------------------------------------------------------------
2005 #### print / output cleaners
2006 #### -------------------------------------------------------------------
2007
2008 # inxi speaks through here. When run by Konversation script alias mode, uses DCOP
2009 # for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e
2010 # note: dcop does not seem able to handle \n so that's being stripped out and replaced with space.
2011 print_screen_output()
2012 {
2013         eval $LOGFS
2014         # the double quotes are needed to avoid losing whitespace in data when certain output types are used
2015         # trim off whitespace at end
2016         local print_data="$( echo -e "$1" )" 
2017
2018         # just using basic debugger stuff so you can tell which thing is printing out the data. This
2019         # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off
2020         # the redundant debugger output which as far as I can tell does exactly nothing to help debugging.
2021         if [[ $DEBUG -gt 5 ]];then
2022                 if [[ $KONVI -eq 1 ]];then
2023                         # konvi doesn't seem to like \n characters, it just prints them literally
2024                         # print_data="$( tr '\n' ' ' <<< "$print_data" )"
2025                         # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'"
2026                         print_data="KP-$KONVI: $print_data"
2027                 elif [[ $KONVI -eq 2 ]];then
2028                         # echo "konvi='$KONVI' saying : '$print_data'"
2029                         print_data="KP-$KONVI: $print_data"
2030                 else
2031                         # echo "printing out: '$print_data'"
2032                         print_data="P: $print_data"
2033                 fi
2034         fi
2035
2036         if [[ $KONVI -eq 1 && $B_DCOP == 'true' ]]; then ## dcop Konversation (<= 1.1 (qt3))
2037                 # konvi doesn't seem to like \n characters, it just prints them literally
2038                 $print_data="$( tr '\n' ' ' <<< "$print_data" )"
2039                 dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data"
2040
2041         elif [[ $KONVI -eq 3 && $B_QDBUS == 'true' ]]; then ## dbus Konversation (> 1.2 (qt4))
2042                 qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data"
2043
2044 #       elif [[ $IRC_CLIENT == 'X-Chat' ]]; then
2045 #               qdbus org.xchat.service print "$print_data\n"
2046
2047         else
2048                 # the -n is needed to avoid double spacing of output in terminal
2049                 echo -ne "$print_data\n"
2050         fi
2051         eval $LOGFE
2052 }
2053
2054 ## this handles all verbose line construction with indentation/line starter
2055 ## args: $1 - null (, actually: " ") or line starter; $2 - line content
2056 create_print_line()
2057 {
2058         eval $LOGFS
2059         local line=$2
2060         printf "${C1}%-${INDENT}s${C2} %s" "$1" "$line"
2061         eval $LOGFE
2062 }
2063
2064 # this removes newline and pipes.
2065 # args: $1 - string to clean
2066 remove_erroneous_chars()
2067 {
2068         eval $LOGFS
2069         ## RS is input record separator
2070         ## gsub is substitute;
2071         gawk '
2072         BEGIN {
2073                 RS=""
2074         }
2075         {
2076                 gsub(/\n$/,"")         ## (newline; end of string) with (nothing)
2077                 gsub(/\n/," ");        ## (newline) with (space)
2078                 gsub(/^ *| *$/, "")    ## (pipe char) with (nothing)
2079                 gsub(/  +/, " ")       ## ( +) with (space)
2080                 gsub(/ [ ]+/, " ")     ## ([ ]+) with (space)
2081                 gsub(/^ +| +$/, "")    ## (pipe char) with (nothing)
2082                 printf $0
2083         }' "$1"      ## prints (returns) cleaned input
2084         eval $LOGFE
2085 }
2086
2087 #### -------------------------------------------------------------------
2088 #### parameter handling, print usage functions.
2089 #### -------------------------------------------------------------------
2090
2091 # Get the parameters. Note: standard options should be lower case, advanced or testing, upper
2092 # args: $1 - full script startup args: $@
2093 get_parameters()
2094 {
2095         eval $LOGFS
2096         local opt='' wget_test='' debug_data_type='' weather_flag='wW:' 
2097         local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false
2098
2099         # if distro maintainers don't want the weather feature disable it
2100         if [[ $B_ALLOW_WEATHER == 'false' ]];then
2101                 weather_flag=''
2102                 
2103         fi
2104         if [[ $1 == '--version' ]];then
2105                 print_version_info
2106                 exit 0
2107         elif [[ $1 == '--help' ]];then
2108                 show_options
2109                 exit 0
2110         elif [[ $1 == '--recommends' ]];then
2111                 check_recommends_user_output
2112                 exit 0
2113         # the short form only runs if no args output args are used
2114         # no need to run through these if there are no args
2115         # reserved for future use: -g for extra Graphics; -m for extra Machine; -d for extra Disk
2116         elif [[ -n $1 ]];then
2117                 while getopts Abc:CdDfFGhHiIlMnNopPrRsSt:uUv:V${weather_flag}xzZ%@:!: opt
2118                 do
2119                         case $opt in
2120                         A)      B_SHOW_AUDIO='true'
2121                                 use_short='false'
2122                                 ;;
2123                         b)      use_short='false'
2124                                 B_SHOW_BASIC_CPU='true'
2125                                 B_SHOW_BASIC_RAID='true'
2126                                 B_SHOW_DISK_TOTAL='true'
2127                                 B_SHOW_GRAPHICS='true'
2128                                 B_SHOW_INFO='true'
2129                                 B_SHOW_MACHINE='true'
2130                                 B_SHOW_NETWORK='true'
2131                                 B_SHOW_SYSTEM='true'
2132                                 ;;
2133                         c)      if [[ -n $( grep -E '^[0-9][0-9]?$' <<< $OPTARG ) ]];then
2134                                         case $OPTARG in
2135                                                 99)
2136                                                         B_RUN_COLOR_SELECTOR='true'
2137                                                         COLOR_SELECTION='global'
2138                                                         ;;
2139                                                 98)
2140                                                         B_RUN_COLOR_SELECTOR='true'
2141                                                         COLOR_SELECTION='irc-console'
2142                                                         ;;
2143                                                 97)
2144                                                         B_RUN_COLOR_SELECTOR='true'
2145                                                         COLOR_SELECTION='irc-virtual-terminal'
2146                                                         ;;
2147                                                 96)
2148                                                         B_RUN_COLOR_SELECTOR='true'
2149                                                         COLOR_SELECTION='irc'
2150                                                         ;;
2151                                                 95)
2152                                                         B_RUN_COLOR_SELECTOR='true'
2153                                                         COLOR_SELECTION='virtual-terminal'
2154                                                         ;;
2155                                                 94)
2156                                                         B_RUN_COLOR_SELECTOR='true'
2157                                                         COLOR_SELECTION='console'
2158                                                         ;;
2159                                                 *)      
2160                                                         B_COLOR_SCHEME_SET='true'
2161                                                         ## note: not sure about this, you'd think user values should be overridden, but
2162                                                         ## we'll leave this for now
2163                                                         if [[ -z $COLOR_SCHEME ]];then
2164                                                                 set_color_scheme "$OPTARG"
2165                                                         fi
2166                                                         ;;
2167                                         esac
2168                                 else
2169                                         error_handler 3 "$OPTARG"
2170                                 fi
2171                                 ;;
2172                         C)      B_SHOW_CPU='true'
2173                                 use_short='false'
2174                                 ;;
2175                         d)      B_SHOW_DISK='true'
2176                                 B_SHOW_FULL_OPTICAL='true'
2177                                 use_short='false'
2178                                 # error_handler 20 "-d has been replaced by -b"
2179                                 ;;
2180                         D)      B_SHOW_DISK='true'
2181                                 use_short='false'
2182                                 ;;
2183                         f)      B_SHOW_CPU='true'
2184                                 B_CPU_FLAGS_FULL='true'
2185                                 use_short='false'
2186                                 ;;
2187                         F)      # B_EXTRA_DATA='true'
2188                                 B_SHOW_ADVANCED_NETWORK='true'
2189                                 B_SHOW_AUDIO='true'
2190                                 # B_SHOW_BASIC_OPTICAL='true'
2191                                 B_SHOW_CPU='true'
2192                                 B_SHOW_DISK='true'
2193                                 B_SHOW_GRAPHICS='true'
2194                                 B_SHOW_INFO='true'
2195                                 B_SHOW_MACHINE='true'
2196                                 B_SHOW_NETWORK='true'
2197                                 B_SHOW_PARTITIONS='true'
2198                                 B_SHOW_RAID='true'
2199                                 B_SHOW_SENSORS='true'
2200                                 B_SHOW_SYSTEM='true'
2201                                 use_short='false'
2202                                 ;;
2203                         G)      B_SHOW_GRAPHICS='true'
2204                                 use_short='false'
2205                                 ;;
2206                         i)      B_SHOW_IP='true'
2207                                 B_SHOW_NETWORK='true'
2208                                 B_SHOW_ADVANCED_NETWORK='true'
2209                                 use_short='false'
2210                                 ;;
2211                         I)      B_SHOW_INFO='true'
2212                                 use_short='false'
2213                                 ;;
2214                         l)      B_SHOW_LABELS='true'
2215                                 B_SHOW_PARTITIONS='true'
2216                                 use_short='false'
2217                                 ;;
2218                         M)      B_SHOW_MACHINE='true'
2219                                 use_short='false'
2220                                 ;;
2221                         n)      B_SHOW_ADVANCED_NETWORK='true'
2222                                 B_SHOW_NETWORK='true'
2223                                 use_short='false'
2224                                 ;;
2225                         N)      B_SHOW_NETWORK='true'
2226                                 use_short='false'
2227                                 ;;
2228                         o)      B_SHOW_UNMOUNTED_PARTITIONS='true'
2229                                 use_short='false'
2230                                 ;;
2231                         p)      B_SHOW_PARTITIONS_FULL='true'
2232                                 B_SHOW_PARTITIONS='true'
2233                                 use_short='false'
2234                                 ;;
2235                         P)      B_SHOW_PARTITIONS='true'
2236                                 use_short='false'
2237                                 ;;
2238                         r)      B_SHOW_REPOS='true'
2239                                 use_short='false'
2240                                 ;;
2241                         R)      B_SHOW_RAID='true'
2242                                 # it turns out only users with mdraid software installed will have raid,
2243                                 # so unless -R is explicitly called, blank -b/-F/-v6 and less output will not show
2244                                 # error if file is missing.
2245                                 B_SHOW_RAID_R='true'
2246                                 use_short='false'
2247                                 ;;
2248                         s)      B_SHOW_SENSORS='true'
2249                                 use_short='false'
2250                                 ;;
2251                         S)      B_SHOW_SYSTEM='true'
2252                                 use_short='false'
2253                                 ;;
2254                         t)      if [[ -n $( grep -E '^(c|m|cm|mc)([1-9]|1[0-9]|20)?$' <<< $OPTARG ) ]];then
2255                                         use_short='false'
2256                                         if [[ -n $( grep -E '[0-9]+' <<< $OPTARG ) ]];then
2257                                                 PS_COUNT=$( sed 's/[^0-9]//g' <<< $OPTARG )
2258                                         fi
2259                                         if [[ -n $( grep 'c' <<< $OPTARG ) ]];then
2260                                                 B_SHOW_PS_CPU_DATA='true'
2261                                         fi
2262                                         if [[ -n $( grep 'm' <<< $OPTARG ) ]];then
2263                                                 B_SHOW_PS_MEM_DATA='true'
2264                                         fi
2265                                 else
2266                                         error_handler 13 "$OPTARG"
2267                                 fi
2268                                 ;;
2269                         u)      B_SHOW_UUIDS='true'
2270                                 B_SHOW_PARTITIONS='true'
2271                                 use_short='false'
2272                                 ;;
2273                         v)      if [[ -n $( grep -E "^[0-9][0-9]?$" <<< $OPTARG ) && $OPTARG -le $VERBOSITY_LEVELS ]];then
2274                                         if [[ $OPTARG -ge 1 ]];then
2275                                                 use_short='false'
2276                                                 B_SHOW_BASIC_CPU='true'
2277                                                 B_SHOW_DISK_TOTAL='true'
2278                                                 B_SHOW_GRAPHICS='true'
2279                                                 B_SHOW_INFO='true'
2280                                                 B_SHOW_SYSTEM='true'
2281                                         fi
2282                                         if [[ $OPTARG -ge 2 ]];then
2283                                                 B_SHOW_BASIC_DISK='true'
2284                                                 B_SHOW_BASIC_RAID='true'
2285                                                 B_SHOW_MACHINE='true'
2286                                                 B_SHOW_NETWORK='true'
2287                                         fi
2288                                         if [[ $OPTARG -ge 3 ]];then
2289                                                 B_SHOW_ADVANCED_NETWORK='true'
2290                                                 B_SHOW_CPU='true'
2291                                                 B_EXTRA_DATA='true'
2292                                         fi
2293                                         if [[ $OPTARG -ge 4 ]];then
2294                                                 B_SHOW_DISK='true'
2295                                                 B_SHOW_PARTITIONS='true'
2296                                         fi
2297                                         if [[ $OPTARG -ge 5 ]];then
2298                                                 B_SHOW_AUDIO='true'
2299                                                 B_SHOW_BASIC_OPTICAL='true'
2300                                                 B_SHOW_SENSORS='true'
2301                                                 B_SHOW_LABELS='true'
2302                                                 B_SHOW_UUIDS='true'
2303                                                 B_SHOW_RAID='true'
2304                                         fi
2305                                         if [[ $OPTARG -ge 6 ]];then
2306                                                 B_SHOW_FULL_OPTICAL='true'
2307                                                 B_SHOW_PARTITIONS_FULL='true'
2308                                                 B_SHOW_UNMOUNTED_PARTITIONS='true'
2309                                                 B_EXTRA_EXTRA_DATA='true'
2310                                         fi
2311                                         if [[ $OPTARG -ge 7 ]];then
2312                                                 B_EXTRA_EXTRA_EXTRA_DATA='true'
2313                                                 B_SHOW_IP='true'
2314                                                 B_SHOW_RAID_R='true'
2315                                         fi
2316                                 else
2317                                         error_handler 4 "$OPTARG"
2318                                 fi
2319                                 ;;
2320                         U)      if [[ $B_ALLOW_UPDATE == 'true' ]];then
2321                                         script_self_updater "$SCRIPT_DOWNLOAD" 'svn server' "$opt"
2322                                 else
2323                                         error_handler 17 "-$opt"
2324                                 fi
2325                                 ;;
2326                         V)      print_version_info
2327                                 exit 0
2328                                 ;;
2329                         w)      B_SHOW_WEATHER=true
2330                                 use_short='false'
2331                                 ;;
2332                         W)      ALTERNATE_WEATHER_LOCATION=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'  <<< $OPTARG )
2333                                 if [[ -n $( grep -Esi '([^,]+,.+|[0-9-]+)' <<< $ALTERNATE_WEATHER_LOCATION ) ]];then
2334                                         B_SHOW_WEATHER=true
2335                                         use_short='false'
2336                                 else
2337                                         error_handler 18 "-$opt: '$OPTARG'" "city,state OR latitude,longitude OR postal/zip code."
2338                                 fi
2339                                 ;;
2340                         # this will trigger either with x, xx, xxx or with Fx but not with xF
2341                         x)      if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2342                                         B_EXTRA_EXTRA_EXTRA_DATA='true'
2343                                 elif [[ $B_EXTRA_DATA == 'true' ]];then
2344                                         B_EXTRA_EXTRA_DATA='true'
2345                                 else
2346                                         B_EXTRA_DATA='true'
2347                                 fi
2348                                 ;;
2349                         z)      B_OUTPUT_FILTER='true'
2350                                 ;;
2351                         Z)      B_OVERRIDE_FILTER='true'
2352                                 ;;
2353                         h)      show_options
2354                                 exit 0
2355                                 ;;
2356                         H)      show_options 'full'
2357                                 exit 0
2358                                 ;;
2359                         ## debuggers and testing tools
2360                         %)      B_HANDLE_CORRUPT_DATA='true'
2361                                 ;;
2362                         @)      if [[ -n $( grep -E "^([1-9]|1[0-4])$" <<< $OPTARG ) ]];then
2363                                         DEBUG=$OPTARG
2364                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2365                                                 B_UPLOAD_DEBUG_DATA='true'
2366                                         fi
2367                                         exec 2>&1
2368                                         # switch on logging only for -@ 8-10
2369                                         case $OPTARG in
2370                                                 8|9|10)
2371                                                         if [[ $OPTARG -eq 10 ]];then
2372                                                                 B_LOG_COLORS='true'
2373                                                         elif [[ $OPTARG -eq 9 ]];then           
2374                                                                 B_LOG_FULL_DATA='true'
2375                                                         fi
2376                                                         B_USE_LOGGING='true'
2377                                                         # pack the logging data for evals function start/end
2378                                                         LOGFS=$LOGFS_STRING
2379                                                         LOGFE=$LOGFE_STRING
2380                                                         create_rotate_logfiles # create/rotate logfiles before we do anything else
2381                                                         ;;
2382                                                 11|12|13|14)
2383                                                         case $OPTARG in
2384                                                                 11)
2385                                                                         debug_data_type='sys'
2386                                                                         ;;
2387                                                                 12)
2388                                                                         debug_data_type='xorg'
2389                                                                         ;;
2390                                                                 13)
2391                                                                         debug_data_type='disk'
2392                                                                         ;;
2393                                                                 14)
2394                                                                         debug_data_type='all'
2395                                                                         ;;
2396                                                         esac
2397                                                         initialize_data
2398                                                         debug_data_collector $debug_data_type
2399                                                         ;;
2400                                         esac
2401                                 else
2402                                         error_handler 9 "$OPTARG"
2403                                 fi
2404                                 ;;
2405                         !)      # test for various supported methods
2406                                 case $OPTARG in
2407                                         1)      B_TESTING_1='true'
2408                                                 ;;
2409                                         2)      B_TESTING_2='true'
2410                                                 ;;
2411                                         3)      B_TESTING_1='true'
2412                                                 B_TESTING_2='true'
2413                                                 ;;
2414                                         1[0-6]|http*)
2415                                                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
2416                                                         case $OPTARG in
2417                                                                 10)
2418                                                                         script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server' "$opt $OPTARG"
2419                                                                         ;;
2420                                                                 11)
2421                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server' "$opt $OPTARG"
2422                                                                         ;;
2423                                                                 12)
2424                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server' "$opt $OPTARG"
2425                                                                         ;;
2426                                                                 13)
2427                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server' "$opt $OPTARG"
2428                                                                         ;;
2429                                                                 14)
2430                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server' "$opt $OPTARG"
2431                                                                         ;;
2432                                                                 15)
2433                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_BSD" 'svn: branch bsd server' "$opt $OPTARG"
2434                                                                         ;;
2435                                                                 16)
2436                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_GNUBSD" 'svn: branch gnubsd server' "$opt $OPTARG"
2437                                                                         ;;
2438                                                                 http*)
2439                                                                         script_self_updater "$OPTARG" 'alt server' "$opt <http...>"
2440                                                                         ;;
2441                                                         esac
2442                                                 else
2443                                                         error_handler 17 "-$opt $OPTARG"
2444                                                 fi
2445                                                 ;;
2446                                         30)
2447                                                 B_RUNNING_IN_SHELL='true'
2448                                                 ;;
2449                                         31)
2450                                                 B_SHOW_HOST='false'
2451                                                 ;;
2452                                         32)
2453                                                 B_SHOW_HOST='true'
2454                                                 ;;
2455                                         ftp*)
2456                                                 ALTERNATE_FTP="$OPTARG"
2457                                                 ;;
2458                                         # for weather function, allows user to set an alternate weather location
2459                                         location=*)
2460                                                 error_handler 19 "-$opt location=" "-W"
2461                                                 ;;
2462                                         *)      error_handler 11 "$OPTARG"
2463                                                 ;;
2464                                 esac
2465                                 ;;
2466                         *)      error_handler 7 "$1"
2467                                 ;;
2468                         esac
2469                 done
2470         fi
2471         ## this must occur here so you can use the debugging flag to show errors
2472         ## Reroute all error messages to the bitbucket (if not debugging)
2473         if [[ $DEBUG -eq 0 ]];then
2474                 exec 2>/dev/null
2475         fi
2476         #((DEBUG)) && exec 2>&1 # This is for debugging konversation
2477
2478         # after all the args have been processed, if no long output args used, run short output
2479         if [[ $use_short == 'true' ]];then
2480                 B_SHOW_SHORT_OUTPUT='true'
2481         fi
2482         # just in case someone insists on using -zZ
2483         if [[ $B_OVERRIDE_FILTER == 'true' ]];then
2484                 B_OUTPUT_FILTER='false'
2485         fi
2486         # change basic to full if user requested it or if arg overrides it
2487         if [[ $B_SHOW_RAID == 'true' && $B_SHOW_BASIC_RAID == 'true' ]];then
2488                 B_SHOW_BASIC_RAID='false'
2489         fi
2490         
2491         
2492         eval $LOGFE
2493 }
2494
2495 ## print out help menu, not including Testing or Debugger stuff because it's not needed
2496 show_options()
2497 {
2498         local color_scheme_count=$(( ${#A_COLOR_SCHEMES[@]} - 1 ))
2499         local partition_string='partition' partition_string_u='Partition'
2500         
2501         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
2502                 print_screen_output "Sorry, you can't run the help option in an IRC client."
2503                 exit 1
2504         fi
2505         if [[ -n $BSD_TYPE ]];then
2506                 partition_string='slice'
2507                 partition_string_u='Slice'
2508         fi
2509         # print_lines_basic "0" "" ""
2510         # print_lines_basic "1" "" ""
2511         # print_lines_basic "2" "" ""
2512         # print_screen_output " "
2513         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."
2514         print_screen_output " "
2515         print_lines_basic "0" "" "The following options if used without -F, -b, or -v will show just option line(s): A, C, D, G, I, M, N, P, R, S, f, i, 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."
2516         
2517         print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
2518         print_screen_output "Output Control Options:"
2519         print_lines_basic "1" "-A" "Audio/sound card information."
2520         print_lines_basic "1" "-b" "Basic output, short form. Like $SCRIPT_NAME^-v^2, only minus hard disk names."
2521         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."
2522         print_lines_basic "1" "" "Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME^-c^11"
2523         print_lines_basic "1" "" "Color selectors for each type display (NOTE: irc and global only show safe color set):"
2524 #       print_screen_output "    Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11"
2525 #       print_screen_output "    Color selectors for each type display (NOTE: irc and global only show safe color set):"
2526         print_lines_basic "2" "94" "Console, out of X"
2527         print_lines_basic "2" "95" "Terminal, running in X - like xTerm"
2528         print_lines_basic "2" "96" "Gui IRC, running in X - like Xchat, Quassel, Konversation etc."
2529         print_lines_basic "2" "97" "Console IRC running in X - like irssi in xTerm"
2530         print_lines_basic "2" "98" "Console IRC not in  X"
2531         print_lines_basic "2" "99" "Global - Overrides/removes all settings. Setting specific removes global."
2532         print_lines_basic "1" "-C" "CPU output, including per CPU clockspeed (if available)."
2533         print_lines_basic "1" "-d" "Optical drive data. Same as -Dd. See also -x and -xx."
2534         print_lines_basic "1" "-D" "Full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB. See also -x and -xx."
2535         print_lines_basic "1" "-f" "All cpu flags, triggers -C. Not shown with -F to avoid spamming. ARM cpus show 'features'."
2536         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 -x -d -f -u -l -o -p -t -r"
2537         print_lines_basic "1" "-G" "Graphic card information (card, display server type/version, resolution, glx renderer, version)."
2538         print_lines_basic "1" "-i" "Wan IP address, and shows local interfaces (requires ifconfig network tool). Same as -Nni. Not shown with -F for user security reasons, you shouldn't paste your local/wan IP."
2539         print_lines_basic "1" "-I" "Information: processes, uptime, memory, irc client (or shell type), $SCRIPT_NAME version."
2540         print_lines_basic "1" "-l" "${partition_string_u} labels. Default: short ${partition_string} -P. For full -p output, use: -pl (or -plu)."
2541         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."
2542         print_lines_basic "1" "-n" "Advanced Network card information. Same as -Nn. Shows interface, speed, mac id, state, etc."
2543         print_lines_basic "1" "-N" "Network card information. With -x, shows PCI BusID, Port number."
2544         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^"
2545         print_lines_basic "1" "-p" "Full ${partition_string} information (-P plus all other detected ${partition_string}s)."
2546         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."
2547         print_lines_basic "1" "-r" "Distro repository data. Supported repo types: APT; PACMAN; PISI; YUM; URPMQ; Ports."
2548         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."
2549         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."
2550         print_lines_basic "1" "-S" "System information: host name, kernel, desktop environment (if in X), distro"
2551         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"
2552         print_lines_basic "1" "" "Make sure to have no space between letters and numbers (-t^cm10 - right, -t^cm^10 - wrong)."
2553         print_lines_basic "1" "-u" "${partition_string_u} UUIDs. Default: short ${partition_string} -P. For full -p output, use: -pu (or -plu)."
2554         print_lines_basic "1" "-v" "Script verbosity levels. Verbosity level number is required. Should not be used with -b or -F"
2555         print_lines_basic "1" "" "Supported levels: 0-${VERBOSITY_LEVELS} Example: $SCRIPT_NAME^-v^4"
2556         print_lines_basic "2" "0" "Short output, same as: $SCRIPT_NAME"
2557         print_lines_basic "2" "1" "Basic verbose, -S + basic CPU + -G + basic Disk + -I."
2558         print_lines_basic "2" "2" "Networking card (-N), Machine (-M) data, shows basic hard disk data (names only), and, if present, basic raid (devices only, and if inactive, notes that). similar to: $SCRIPT_NAME^-b"
2559         print_lines_basic "2" "3" "Advanced CPU (-C), network (-n) data, and switches on -x advanced data option."
2560         print_lines_basic "2" "4" "${partition_string_u} size/filled data (-P) for (if present):/, /home, /var/, /boot. Shows full disk data (-D)."
2561         print_lines_basic "2" "5" "Audio card (-A); sensors (-s), ${partition_string} label (-l) and UUID (-u), short form of optical drives, standard raid data (-R)."
2562         print_lines_basic "2" "6" "Full ${partition_string} (-p), unmounted ${partition_string} (-o), optical drive (-d), full raid; triggers -xx."
2563         print_lines_basic "2" "7" "Network IP data (-i); triggers -xxx."
2564         
2565         # if distro maintainers don't want the weather feature disable it
2566         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2567                 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."
2568                 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"
2569         fi
2570         print_lines_basic "1" "-x" "Adds the following extra data (only works with verbose or line output, not short form):"
2571         print_lines_basic "2" "-C" "CPU Flags, Bogomips on Cpu;"
2572         print_lines_basic "2" "-d" "Extra optical drive data; adds rev version to optical drive."
2573         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"
2574         print_lines_basic "2" "-G" "Direct rendering status for Graphics (in X)."
2575         print_lines_basic "2" "-G" "(for single gpu, nvidia driver) screen number gpu is running on."
2576         print_lines_basic "2" "-i" "IPv6 as well for LAN interface (IF) devices."
2577         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)."
2578         print_lines_basic "2" "-N -A" "Version/port(s)/driver version (if available) for Network/Audio;"
2579         print_lines_basic "2" "-N -A -G" "Network, audio, graphics, shows PCI Bus ID/Usb ID number of card."
2580         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"
2581         print_lines_basic "2" "-S" "Desktop toolkit if avaliable (GNOME/XFCE/KDE only); Kernel gcc version"
2582         print_lines_basic "2" "-t" "Memory use output to cpu (-xt c), and cpu use to memory (-xt m)."
2583         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2584                 print_lines_basic "2" "-w -W" "Wind speed and time zone (-w only)."
2585         fi
2586         print_lines_basic "1" "-xx" "Show extra, extra data (only works with verbose or line output, not short form):"
2587         print_lines_basic "2" "-A" "Chip vendor:product ID for each audio device."
2588         print_lines_basic "2" "-D" "Disk serial number."
2589         print_lines_basic "2" "-G" "Chip vendor:product ID for each video card."
2590         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."
2591         print_lines_basic "2" "-M" "Chassis information, bios rom size (dmidecode only), if data for either is available."
2592         print_lines_basic "2" "-N" "Chip vendor:product ID for each nic."
2593         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."
2594         print_lines_basic "2" "-S" "Display manager (dm) in desktop output, if in X (like kdm, gdm3, lightdm)."
2595         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2596                 print_lines_basic "2" "-w -W" "Humidity, barometric pressure."
2597         fi
2598         print_lines_basic "2" "-@ 11-14" "Automatically uploads debugger data tar.gz file to ftp.techpatterns.com. EG: $SCRIPT_NAME^-xx@14"
2599         print_lines_basic "1" "-xxx" "Show extra, extra, extra data (only works with verbose or line output, not short form):"
2600         print_lines_basic "2" "-S" "Panel/shell information in desktop output, if in X (like gnome-shell, cinnamon, mate-panel)."
2601         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2602                 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)."
2603         fi
2604         print_lines_basic "1" "-z" "Security filters for IP/Mac addresses, location, user home directory name. Default on for irc clients."
2605         print_lines_basic "1" "-Z" "Absolute override for output filters. Useful for debugging networking issues in irc for example."
2606         print_screen_output " "
2607         print_screen_output "Additional Options:"
2608         print_lines_basic "4" "-h --help" "This help menu."
2609         print_lines_basic "4" "-H" "This help menu, plus developer options. Do not use dev options in normal operation!"
2610         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. "
2611         if [[ $B_ALLOW_UPDATE == 'true' ]];then
2612                 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."
2613         fi
2614         print_lines_basic "4" "-V --version" "$SCRIPT_NAME version information. Prints information then exits."
2615         print_screen_output " "
2616         print_screen_output "Debugging Options:"
2617         print_lines_basic "1" "-%" "Overrides defective or corrupted data."
2618         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."
2619         print_lines_basic "2" "1-7" "On screen debugger output"
2620         print_lines_basic "2" "8" "Basic logging"
2621         print_lines_basic "2" "9" "Full file/sys info logging"
2622         print_lines_basic "2" "10" "Color logging."
2623         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>"
2624         print_lines_basic "1" "" "For alternate ftp upload locations: Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
2625         print_lines_basic "2" "11" "With data file of xiin read of /sys."
2626         print_lines_basic "2" "12" "With xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc."
2627         print_lines_basic "2" "13" "With data from dev, disks, ${partition_string}s, etc., plus xiin data file."
2628         print_lines_basic "2" "14" "Everything, full data collection."
2629         print_screen_output " "
2630         print_screen_output "Advanced Options:"
2631         print_lines_basic "1" "-! 31" "Turns off hostname in output. Useful if showing output from servers etc."
2632         print_lines_basic "1" "-! 32" "Turns on hostname in output. Overrides global B_SHOW_HOST='false'"
2633         
2634         if [[ $1 == 'full' ]];then
2635                 print_screen_output " "
2636                 print_screen_output "Developer and Testing Options (Advanced):"
2637                 print_lines_basic "1" "-! 1" "Sets testing flag B_TESTING_1='true' to trigger testing condition 1."
2638                 print_lines_basic "1" "-! 2" "Sets testing flag B_TESTING_2='true' to trigger testing condition 2."
2639                 print_lines_basic "1" "-! 3" "Sets flags B_TESTING_1='true' and B_TESTING_2='true'."
2640                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
2641                         print_lines_basic "1" "-! 10" "Triggers an update from the primary dev download server instead of svn."
2642                         print_lines_basic "1" "-! 11" "Triggers an update from svn branch one - if present, of course."
2643                         print_lines_basic "1" "-! 12" "Triggers an update from svn branch two - if present, of course."
2644                         print_lines_basic "1" "-! 13" "Triggers an update from svn branch three - if present, of course."
2645                         print_lines_basic "1" "-! 14" "Triggers an update from svn branch four - if present, of course."
2646                         print_lines_basic "1" "-! 15" "Triggers an update from svn branch BSD - if present, of course."
2647                         print_lines_basic "1" "-! 16" "Triggers an update from svn branch GNUBSD - if present, of course."
2648                         print_lines_basic "1" "-! <http://......>" "Triggers an update from whatever server you list."
2649                 fi
2650                 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. "
2651                 print_lines_basic "1" "" "Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
2652         fi
2653         print_screen_output " "
2654 }
2655
2656 # uses $TERM_COLUMNS to set width using $COLS_MAX as max width
2657 # IMPORTANT: minimize use of subshells here or the output is too slow
2658 # args: $1 - 0 1 2 3 4 for indentation level; $2 -line starter, like -m; $3 - content of block.
2659 print_lines_basic()
2660 {
2661         local line_width=$COLS_MAX
2662         local print_string='' indent_inner='' indent_full='' indent_x='' 
2663         local indent_working='' indent_working_full=''
2664         local line_starter='' line_1_starter='' line_x_starter='' 
2665         # note: to create a padded string below
2666         local fake_string=' ' temp_count='' line_count='' spacer=''
2667         local indent_main=6 indent_x='' b_indent_x='true' 
2668         
2669         case $1 in
2670                 # for no options, start at left edge
2671                 0)      indent_full=0
2672                         line_1_starter=''
2673                         line_x_starter=''
2674                         b_indent_x='false'
2675                         ;;
2676                 1)      indent_full=$indent_main
2677                         temp_count=${#2}
2678                         if [[ $temp_count -le $indent_full ]];then
2679                                 indent_working=$indent_full
2680                         else
2681                                 indent_working=$temp_count #$(( $temp_count + 1 ))
2682                         fi
2683                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2684                         ;;
2685                 # first left pad 2 and 3, then right pad them
2686                 2)      indent_full=$(( $indent_main + 6 ))
2687                         indent_inner=3
2688                         temp_count=${#2}
2689                         if [[ $temp_count -le $indent_inner ]];then
2690                                 indent_working=$indent_inner
2691                                 #indent_working_full=$indent_full
2692                         else
2693                                 indent_working=$(( $temp_count + 1 ))
2694                                 #indent_working_full=$(( $indent_full - $indent_inner - 1 ))
2695                         fi
2696                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2697                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
2698                         ;;
2699                 3)      indent_full=$(( $indent_main + 8 ))
2700                         indent_inner=3
2701                         temp_count=${#2}
2702                         if [[ $temp_count -le $indent_inner ]];then
2703                                 indent_working=$indent_inner
2704                         else
2705                                 indent_working=$(( $temp_count + 1 ))
2706                         fi
2707                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2708                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
2709                         ;;
2710                 # for long options
2711                 4)      indent_full=$(( $indent_main + 8 ))
2712                         temp_count=${#2}
2713                         if [[ $temp_count -lt $indent_full ]];then
2714                                 indent_working=$indent_full
2715                         else
2716                                 indent_working=$temp_count #$(( $temp_count + 1 ))
2717                         fi
2718                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2719                         ;;
2720         esac
2721         
2722         if [[ $b_indent_x == 'true' ]];then
2723                 indent_x=$(( $indent_full + 1 ))
2724                 line_x_starter="$(printf "%${indent_x}s" '')"
2725         fi
2726         
2727         line_count=$(( $line_width - $indent_full ))
2728         
2729         # bash loop is slow, only run this if required
2730         if [[ ${#3} -gt $line_count ]];then
2731                 for word in $3
2732                 do
2733                         temp_string="$print_string$spacer$word"
2734                         spacer=' '
2735                         if [[ ${#temp_string} -lt $line_count ]];then
2736                                 print_string=$temp_string # lose any white space start/end
2737                                 # echo -n $(( $line_width - $indent_full ))
2738                         else
2739                                 if [[ -n $line_1_starter ]];then
2740                                         line_starter="$line_1_starter"
2741                                         line_1_starter=''
2742                                 else
2743                                         line_starter="$line_x_starter"
2744                                 fi
2745                                 # clean up forced connections, ie, stuff we don't want wrapping
2746                                 print_string=${print_string//\^/ }
2747                                 print_screen_output "$line_starter$print_string"
2748                                 print_string="$word$spacer" # needed to handle second word on new line
2749                                 temp_string=''
2750                                 spacer=''
2751                         fi
2752                 done
2753         else
2754                 # echo no loop
2755                 print_string=$3
2756         fi
2757         # print anything left over
2758         if [[ -n $print_string ]];then
2759                 if [[ -n $line_1_starter ]];then
2760                         line_starter="$line_1_starter"
2761                         line_1_starter=''
2762                 else
2763                         line_starter="$line_x_starter"
2764                 fi
2765                 print_string=${print_string//\^/ }
2766                 print_screen_output "$line_starter$print_string"
2767         fi
2768 }
2769 # 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'
2770 # 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'
2771 # print_lines_basic '2' '12' 'and its sss substring'
2772 # 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'
2773 # exit
2774
2775 ## print out version information for -V/--version
2776 print_version_info()
2777 {
2778         # if not in PATH could be either . or directory name, no slash starting
2779         local script_path=$SCRIPT_PATH script_symbolic_start=''
2780         if [[ $script_path == '.' ]];then
2781                 script_path=$( pwd )
2782         elif [[ -z $( grep '^/' <<< "$script_path" ) ]];then
2783                 script_path="$( pwd )/$script_path"
2784         fi
2785         # handle if it's a symbolic link, rare, but can happen with script directories in irc clients
2786         # which would only matter if user starts inxi with -! 30 override in irc client
2787         if [[ -L $script_path/$SCRIPT_NAME ]];then
2788                 script_symbolic_start=$script_path/$SCRIPT_NAME
2789                 script_path=$( readlink $script_path/$SCRIPT_NAME )
2790                 script_path=$( dirname $script_path )
2791         fi
2792         local last_modified=$( parse_version_data 'date' ) 
2793         local year_modified=$( gawk '{print $NF}' <<< "$last_modified" )
2794         
2795         print_screen_output "$SCRIPT_NAME $SCRIPT_VERSION_NUMBER-$SCRIPT_PATCH_NUMBER ($last_modified)"
2796         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
2797                 print_screen_output "Program Location: $script_path"
2798                 if [[ -n $script_symbolic_start ]];then
2799                         print_screen_output "Started via symbolic link: $script_symbolic_start"
2800                 fi
2801                 print_lines_basic "0" "" "Website:^http://inxi.goooglecode.com"
2802                 print_lines_basic "0" "" "IRC:^irc.oftc.net channel:^#smxi"
2803                 print_lines_basic "0" "" "Forums:^http://techpatterns.com/forums/forum-33.html"
2804                 print_screen_output " "
2805                 print_lines_basic "0" "" "$SCRIPT_NAME - the universal, portable, system information tool for console and irc."
2806                 print_screen_output " "
2807                 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."
2808                 print_lines_basic "0" "" "Subsequent changes and modifications (after Infobash 3.02): Copyright (C) 2008-$year_modified Scott Rogers, Harald Hope, aka trash80 & h2"
2809                 print_screen_output " "
2810                 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)"
2811         fi
2812 }
2813
2814 ########################################################################
2815 #### MAIN FUNCTIONS
2816 ########################################################################
2817
2818 #### -------------------------------------------------------------------
2819 #### initial startup stuff
2820 #### -------------------------------------------------------------------
2821
2822 # Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION
2823 get_start_client()
2824 {
2825         eval $LOGFS
2826         local Irc_Client_Path='' irc_client_path_lower='' non_native_konvi='' i=''
2827         local B_Non_Native_App='false' pppid='' App_Working_Name=''
2828         local b_qt4_konvi='false' ps_parent=''
2829
2830         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
2831                 IRC_CLIENT='Shell'
2832                 unset IRC_CLIENT_VERSION
2833         # elif [[ -n $PPID ]];then
2834         elif [[ -n $PPID && -f /proc/$PPID/exe ]];then
2835                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2836                         B_OUTPUT_FILTER='true'
2837                 fi
2838                 Irc_Client_Path=$( readlink /proc/$PPID/exe )
2839                 # Irc_Client_Path=$( ps -p $PPID | gawk '!/[[:space:]]*PID/ {print $5}'  )
2840                 # echo $( ps -p $PPID )
2841                 irc_client_path_lower=$( tr '[:upper:]' '[:lower:]' <<< $Irc_Client_Path )
2842                 App_Working_Name=$( basename $irc_client_path_lower )
2843                 # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients
2844                 # report themselves as perl or unknown shell. IE:  when konversation starts inxi
2845                 # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc
2846                 # note: perl can report as: perl5.10.0, so it needs wildcard handling
2847                 case $App_Working_Name in
2848                         # bsd will never use this section
2849                         bash|dash|sh|python*|perl*)     # We want to know who wrapped it into the shell or perl.
2850                                 pppid="$( ps -p $PPID -o ppid --no-headers | sed 's/[[:space:]]//g' )"
2851                                 if [[ -n $pppid && -f /proc/$pppid/exe ]];then
2852                                         Irc_Client_Path="$( readlink /proc/$pppid/exe )"
2853                                         irc_client_path_lower="$( tr '[:upper:]' '[:lower:]' <<< $Irc_Client_Path )"
2854                                         App_Working_Name=$( basename $irc_client_path_lower )
2855                                         B_Non_Native_App='true'
2856                                 fi
2857                                 ;;
2858                 esac
2859                 # sets version number if it can find it
2860                 get_irc_client_version
2861         else
2862                 ## lets look to see if qt4_konvi is the parent.  There is no direct way to tell, so lets infer it.
2863                 ## because $PPID does not work with qt4_konvi, the above case does not work
2864                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2865                         B_OUTPUT_FILTER='true'
2866                 fi
2867                 b_qt4_konvi=$( is_this_qt4_konvi )
2868                 if [[ $b_qt4_konvi == 'true' ]];then
2869                         KONVI=3
2870                         IRC_CLIENT='Konversation'
2871                         IRC_CLIENT_VERSION=" $( konversation -v | gawk '
2872                                 /Konversation:/ {
2873                                         for ( i=2; i<=NF; i++ ) {
2874                                                 if (i == NF) {
2875                                                         print $i
2876                                                 }
2877                                                 else {
2878                                                         printf $i" "
2879                                                 }
2880                                         }
2881                                         exit
2882                                 }' )"
2883                 else
2884                         # this should handle certain cases where it's ssh or some other startup tool
2885                         # that falls through all the other tests
2886                         if [[ $BSD_TYPE != 'bsd' ]];then
2887                                 App_Working_Name=$(ps -p $PPID --no-headers 2>/dev/null | gawk '{print $NF}' )
2888                         else
2889                                 # without --no-headers we need the second line
2890                                 App_Working_Name=$(ps -p $PPID 2>/dev/null | gawk '/^[0-9]+/ {print $5}' )
2891                         fi
2892                         
2893                         if [[ -n $App_Working_Name ]];then
2894                                 Irc_Client_Path=$App_Working_Name
2895                                 B_Non_Native_App='false'
2896                                 get_irc_client_version
2897                                 if [[ -z $IRC_CLIENT ]];then
2898                                         IRC_CLIENT=$App_Working_Name
2899                                 fi
2900                         else
2901                                 IRC_CLIENT="PPID=\"$PPID\" - empty?"
2902                                 unset IRC_CLIENT_VERSION
2903                         fi
2904                 fi
2905         fi
2906
2907         log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID"
2908         eval $LOGFE
2909 }
2910 # note: all variables set in caller so no need to pass
2911 get_irc_client_version()
2912 {
2913         local file_data=''
2914         # replacing loose detection with tight detection, bugs will be handled with app names
2915         # as they appear.
2916         case $App_Working_Name in
2917                 # check for shell first
2918                 bash|dash|sh)
2919                         unset IRC_CLIENT_VERSION
2920                         IRC_CLIENT="Shell wrapper"
2921                         ;;
2922                 # now start on irc clients, alphabetically
2923                 bitchx)
2924                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
2925                         /Version/ {
2926                                 a=tolower($2)
2927                                 gsub(/[()]|bitchx-/,"",a)
2928                                 print a
2929                                 exit
2930                         }
2931                         $2 == "version" {
2932                                 a=tolower($3)
2933                                 sub(/bitchx-/,"",a)
2934                                 print a
2935                                 exit
2936                         }' )"
2937                         B_CONSOLE_IRC='true'
2938                         IRC_CLIENT="BitchX"
2939                         ;;
2940                 finch)
2941                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2942                                 print $2
2943                         }' )"
2944                         B_CONSOLE_IRC='true'
2945                         IRC_CLIENT="Finch"
2946                         ;;
2947                 gaim)
2948                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2949                                 print $2
2950                         }' )"
2951                         IRC_CLIENT="Gaim"
2952                         ;;
2953                 hexchat)
2954                         # the hexchat author decided to make --version/-v return a gtk dialogue box, lol...
2955                         # so we need to read the actual config file for hexchat. Note that older hexchats
2956                         # used xchat config file, so test first for default, then legacy. Because it's possible
2957                         # for this file to be use edited, doing some extra checks here.
2958                         if [[ -f ~/.config/hexchat/hexchat.conf ]];then
2959                                 file_data="$( cat ~/.config/hexchat/hexchat.conf )"
2960                         elif [[ -f  ~/.config/hexchat/xchat.conf ]];then
2961                                 file_data="$( cat ~/.config/hexchat/xchat.conf )"
2962                         fi
2963                         if [[ -n $file_data ]];then
2964                                 IRC_CLIENT_VERSION=$( gawk '
2965                                 BEGIN {
2966                                         IGNORECASE=1
2967                                         FS="="
2968                                 }
2969                                 /^[[:space:]]*version/ {
2970                                         # get rid of the space if present
2971                                         gsub(/[[:space:]]*/, "", $2 )
2972                                         print $2
2973                                         exit # usually this is the first line, no point in continuing
2974                                 }' <<< "$file_data" )
2975                                 
2976                                 IRC_CLIENT_VERSION=" $IRC_CLIENT_VERSION"
2977                         else
2978                                 IRC_CLIENT_VERSION=' N/A'
2979                         fi
2980                         IRC_CLIENT="HexChat"
2981                         ;;
2982                 ircii)
2983                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2984                                 print $3
2985                         }' )"
2986                         B_CONSOLE_IRC='true'
2987                         IRC_CLIENT="ircII"
2988                         ;;
2989                 irssi-text|irssi)
2990                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2991                                 print $2
2992                         }' )"
2993                         B_CONSOLE_IRC='true'
2994                         IRC_CLIENT="Irssi"
2995                         ;;
2996                 konversation) ## konvi < 1.2 (qt4)
2997                         # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script
2998                         if [[ $B_Non_Native_App == 'true' ]];then  ## true negative is confusing
2999                                 KONVI=2
3000                         else # if native app
3001                                 KONVI=1
3002                         fi
3003                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
3004                         /Konversation:/ {
3005                                 for ( i=2; i<=NF; i++ ) {
3006                                         if (i == NF) {
3007                                                 print $i
3008                                         }
3009                                         else {
3010                                                 printf $i" "
3011                                         }
3012                                 }
3013                                 exit
3014                         }' )"
3015
3016                         T=($IRC_CLIENT_VERSION)
3017                         if [[ ${T[0]} == *+* ]];then
3018                                 # < Sho_> locsmif: The version numbers of SVN versions look like this:
3019                                 #         "<version number of last release>+ #<build number", i.e. "1.0+ #3177" ...
3020                                 #         for releases we remove the + and build number, i.e. "1.0" or soon "1.0.1"
3021                                 IRC_CLIENT_VERSION=" CVS $IRC_CLIENT_VERSION"
3022                                 T2="${T[0]/+/}"
3023                         else
3024                                 IRC_CLIENT_VERSION=" ${T[0]}"
3025                                 T2="${T[0]}"
3026                         fi
3027                         # Remove any dots except the first, and make sure there are no trailing zeroes,
3028                         T2=$( echo "$T2" | gawk '{
3029                                 sub(/\./, " ")
3030                                 gsub(/\./, "")
3031                                 sub(/ /, ".")
3032                                 printf("%g\n", $0)
3033                         }' )
3034                         # Since Konversation 1.0, the DCOP interface has changed a bit: dcop "$DCPORT" Konversation ..etc
3035                         # becomes : dcop "$DCPORT" default ... or dcop "$DCPORT" irc ..etc. So we check for versions smaller
3036                         # than 1 and change the DCOP parameter/object accordingly.
3037                         if [[ ${T2} -lt 1 ]];then
3038                                 DCOPOBJ="Konversation"
3039                         fi
3040                         IRC_CLIENT="Konversation"
3041                         ;;
3042                 kopete)
3043                         IRC_CLIENT_VERSION=" $( kopete -v | gawk '
3044                         /Kopete:/ {
3045                                 print $2
3046                                 exit
3047                         }' )"
3048                         IRC_CLIENT="Kopete"
3049                         ;;
3050                 kvirc)
3051                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>&1 | gawk '{
3052                                 for ( i=2; i<=NF; i++) {
3053                                         if ( i == NF ) {
3054                                                 print $i
3055                                         }
3056                                         else {
3057                                                 printf $i" "
3058                                         }
3059                                 }
3060                                 exit
3061                                 }' )"
3062                         IRC_CLIENT="KVIrc"
3063                         ;;
3064                 pidgin)
3065                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3066                                 print $2
3067                         }' )"
3068                         IRC_CLIENT="Pidgin"
3069                         ;;
3070                 quassel*)
3071                         # sample: quassel -v
3072                         # Qt: 4.5.0
3073                         # KDE: 4.2.65 (KDE 4.2.65 (KDE 4.3 >= 20090226))
3074                         # Quassel IRC: v0.4.0 [+60] (git-22effe5)
3075                         # note: early < 0.4.1 quassels do not have -v
3076                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>/dev/null | gawk -F ': ' '
3077                         BEGIN {
3078                                 IGNORECASE=1
3079                                 clientVersion=""
3080                         }
3081                         /Quassel IRC/ {
3082                                 clientVersion = $2
3083                         }
3084                         END {
3085                                 # this handles pre 0.4.1 cases with no -v
3086                                 if ( clientVersion == "" ) {
3087                                         clientVersion = "(pre v0.4.1)"
3088                                 }
3089                                 print clientVersion
3090                         }' )"
3091                         # now handle primary, client, and core. quasselcore doesn't actually
3092                         # handle scripts with exec, but it's here just to be complete
3093                         case $App_Working_Name in
3094                                 quassel)
3095                                         IRC_CLIENT="Quassel [M]"
3096                                         ;;
3097                                 quasselclient)
3098                                         IRC_CLIENT="Quassel"
3099                                         ;;
3100                                 quasselcore)
3101                                         IRC_CLIENT="Quassel (core)"
3102                                         ;;
3103                         esac
3104                         ;;
3105                 weechat-curses)
3106                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v ) "
3107                         B_CONSOLE_IRC='true'
3108                         IRC_CLIENT="Weechat"
3109                         ;;
3110                 xchat-gnome)
3111                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3112                                 print $2
3113                         }' )"
3114                         IRC_CLIENT="X-Chat-Gnome"
3115                         ;;
3116                 xchat)
3117                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3118                                 print $2
3119                         }' )"
3120                         IRC_CLIENT="X-Chat"
3121                         ;;
3122                 # then do some perl type searches, do this last since it's a wildcard search
3123                 perl*|ksirc|dsirc)
3124                         unset IRC_CLIENT_VERSION
3125                         # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client
3126                         get_cmdline $PPID
3127                         for (( i=0; i <= $CMDL_MAX; i++ ))
3128                         do
3129                                 case ${A_CMDL[i]} in
3130                                         *dsirc*)
3131                                         IRC_CLIENT="KSirc"
3132                                         # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
3133                                         # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
3134                                         # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
3135                                         # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
3136                                         # dsirc is the program that runs inxi, therefore that is the parent process that we see.
3137                                         # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
3138                                         # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
3139                                         # (KSirc sucks anyway ;)
3140                                         IRC_CLIENT_VERSION=" $( ksirc -v | gawk '
3141                                         /KSirc:/ {
3142                                                 print $2
3143                                                 exit
3144                                         }' )"
3145                                         break
3146                                         ;;
3147                                 esac
3148                         done
3149                         B_CONSOLE_IRC='true'
3150                         set_perl_python_konvi "$App_Working_Name"
3151                         ;;
3152                 python*)
3153                         # B_CONSOLE_IRC='true' # are there even any python type console irc clients? check.
3154                         set_perl_python_konvi "$App_Working_Name"
3155                         ;;
3156                 # then unset, set unknown data
3157                 *)      
3158                         IRC_CLIENT="Unknown : ${Irc_Client_Path##*/}"
3159                         unset IRC_CLIENT_VERSION
3160                         ;;
3161         esac
3162         if [[ $SHOW_IRC -lt 2 ]];then
3163                 unset IRC_CLIENT_VERSION
3164         fi
3165 }
3166
3167 # args: $1 - App_Working_Name
3168 set_perl_python_konvi()
3169 {
3170         if [[ -z $IRC_CLIENT_VERSION ]];then
3171                 # this is a hack to try to show konversation if inxi is running but started via /cmd
3172                 if [[ -n $( grep -i 'konversation' <<< "$Ps_aux_Data" | grep -v 'grep' ) && $B_RUNNING_IN_DISPLAY == 'true' ]];then
3173                         IRC_CLIENT='Konversation'
3174                         IRC_CLIENT_VERSION=" $( konversation --version 2>/dev/null | gawk '/^Konversation/ {print $2}' )"
3175                         B_CONSOLE_IRC='false'
3176                 else
3177                         IRC_CLIENT="Unknown $1 client"
3178                 fi
3179         fi
3180 }
3181
3182 ## try to infer the use of Konversation >= 1.2, which shows $PPID improperly
3183 ## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running,
3184 ## and all other irc clients are not running.  
3185 is_this_qt4_konvi()
3186 {
3187         local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' 
3188         local konvi='' konvi_qt4_ver='' b_is_qt4=''
3189         
3190         # fringe cases can throw error, always if untested app, use 2>/dev/null after testing if present
3191         if [[ $B_QDBUS == 'true' ]];then
3192                 konvi_dbus_exist=$( qdbus 2>/dev/null | grep "org.kde.konversation" )
3193         fi
3194         # sabayon uses /usr/share/apps/konversation as path
3195         if [[ -n $konvi_dbus_exist ]] && [[ -e /usr/share/kde4/apps/konversation || -e  /usr/share/apps/konversation ]]; then
3196                 konvi_pid=$( ps -A | gawk 'BEGIN{IGNORECASE=1} /konversation/ { print $1 }' ) 
3197                 konvi_home_dir=$( readlink /proc/$konvi_pid/exe )
3198                 konvi=$( echo $konvi_home_dir | sed "s/\// /g" )
3199                 konvi=($konvi)
3200
3201                 if [[ ${konvi[2]} == 'konversation' ]];then     
3202                         konvi_qt4_ver=$( konversation -v | grep -i 'konversation' )
3203                         # note: we need to change this back to a single dot number, like 1.3, not 1.3.2
3204                         konvi_qt4_client=$( echo "$konvi_qt4_ver" | gawk '{ print $2 }' | cut -d '.' -f 1,2 )
3205
3206                         if [[ $konvi_qt4_client > 1.1 ]]; then
3207                                 b_is_qt4='true'
3208                         fi
3209                 fi
3210         else
3211                 konvi_qt4="qt3"
3212                 b_is_qt4='false'
3213         fi
3214         log_function_data "b_is_qt4: $b_is_qt4"
3215         echo $b_is_qt4
3216         ## for testing this module
3217         #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]}"
3218 }
3219
3220 # This needs some cleanup and comments, not quite understanding what is happening, although generally output is known
3221 # Parse the null separated commandline under /proc/<pid passed in $1>/cmdline
3222 # args: $1 - $PPID
3223 get_cmdline()
3224 {
3225         eval $LOGFS
3226         local i=0 ppid=$1
3227
3228         if [[ ! -e /proc/$ppid/cmdline ]];then
3229                 echo 0
3230                 return
3231         fi
3232         ##print_screen_output "Marker"
3233         ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)"
3234         unset A_CMDL
3235         ## note: need to figure this one out, and ideally clean it up and make it readable
3236         while read -d $'\0' L && [[ $i -lt 32 ]]
3237         do
3238                 A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ##
3239         done < /proc/$ppid/cmdline
3240         ##print_screen_output "\$i='$i'"
3241         if [[ $i -eq 0 ]];then
3242                 A_CMDL[0]=$(< /proc/$ppid/cmdline)
3243                 if [[ -n ${A_CMDL[0]} ]];then
3244                         i=1
3245                 fi
3246         fi
3247         CMDL_MAX=$i
3248         log_function_data "CMDL_MAX: $CMDL_MAX"
3249         eval $LOGFE
3250 }
3251
3252 #### -------------------------------------------------------------------
3253 #### get data types
3254 #### -------------------------------------------------------------------
3255 ## create array of sound cards installed on system, and if found, use asound data as well
3256 get_audio_data()
3257 {
3258         eval $LOGFS
3259         local i='' alsa_data='' audio_driver='' device_count='' temp_array=''
3260
3261         IFS=$'\n'
3262         # this first step handles the drivers for cases where the second step fails to find one
3263         device_count=$( echo "$Lspci_v_Data" | grep -iEc '(multimedia audio controller|audio device)' )
3264         if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3265                 audio_driver=$( gawk -F ']: ' '
3266                 BEGIN {
3267                         IGNORECASE=1
3268                 }
3269                 # filtering out modems and usb devices like webcams, this might get a
3270                 # usb audio card as well, this will take some trial and error
3271                 $0 !~ /modem|usb|webcam/ {
3272                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3273                         gsub(/^ +| +$/,"",driver)
3274                         if ( driver != "" ){
3275                                 print driver
3276                         }
3277                 }' $FILE_ASOUND_DEVICE ) 
3278                 log_function_data 'cat' "$FILE_ASOUND_DEVICE"
3279         fi
3280
3281         # this is to safeguard against line breaks from results > 1, which if inserted into following
3282         # array will create a false array entry. This is a hack, not a permanent solution.
3283         audio_driver=$( echo $audio_driver )
3284         # now we'll build the main audio data, card name, driver, and port. If no driver is found,
3285         # and if the first method above is not null, and one card is found, it will use that instead.
3286         A_AUDIO_DATA=( $( echo "$Lspci_v_Data" | gawk -F ': ' -v audioDriver="$audio_driver" '
3287         BEGIN {
3288                 IGNORECASE=1
3289         }
3290         /multimedia audio controller|audio device/ {
3291                 audioCard=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
3292                 # The doublequotes are necessary because of the pipes in the variable.
3293                 gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard)
3294                 gsub(/,/, " ", audioCard)
3295                 gsub(/^ +| +$/, "", audioCard)
3296                 gsub(/ [ \t]+/, " ", audioCard)
3297                 aPciBusId[audioCard] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
3298                 cards[audioCard]++
3299
3300                 # loop until you get to the end of the data block
3301                 while (getline && !/^$/) {
3302                         gsub( /,/, "", $0 )
3303                         if (/driver in use/) {
3304                                 drivers[audioCard] = drivers[audioCard] gensub( /(.*): (.*)/ ,"\\2", "g" ,$0 ) ""
3305                         }
3306                         else if (/kernel modules:/) {
3307                                 modules[audioCard] = modules[audioCard] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
3308                         }
3309                         else if (/I\/O/) {
3310                                 portsTemp = gensub(/\t*I\/O ports at (.*) \[.*\]/,"\\1","g",$0)
3311                                 ports[audioCard] = ports[audioCard] portsTemp " "
3312                         }
3313                 }
3314         }
3315
3316         END {
3317                 j=0
3318                 for (i in cards) {
3319                         useDrivers=""
3320                         useModules=""
3321                         usePorts=""
3322                         usePciBusId=""
3323                          
3324                         if (cards[i]>1) {
3325                                 a[j]=cards[i]"x "i
3326                                 if (drivers[i] != "") {
3327                                         useDrivers=drivers[i]
3328                                 }
3329                         }
3330                         else {
3331                                 a[j]=i
3332                                 # little trick here to try to catch the driver if there is
3333                                 # only one card and it was null, from the first test of asound/cards
3334                                 if (drivers[i] != "") {
3335                                         useDrivers=drivers[i]
3336                                 }
3337                                 else if ( audioDriver != "" ) {
3338                                         useDrivers=audioDriver
3339                                 }
3340                         }
3341                         if (ports[i] != "") {
3342                                 usePorts = ports[i]
3343                         }
3344                         if (modules[i] != "" ) {
3345                                 useModules = modules[i]
3346                         }
3347                         if ( aPciBusId[i] != "" ) {
3348                                 usePciBusId = aPciBusId[i]
3349                         }
3350                         # create array primary item for master array
3351                         sub( / $/, "", usePorts ) # clean off trailing whitespace
3352                         print a[j] "," useDrivers "," usePorts "," useModules "," usePciBusId
3353                         j++
3354                 }
3355         }') )
3356
3357         # in case of failure of first check do this instead
3358         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3359                 A_AUDIO_DATA=( $( gawk -F ']: ' '
3360                 BEGIN {
3361                         IGNORECASE=1
3362                 }
3363                 $1 !~ /modem/ && $2 !~ /modem/ {
3364                         card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 )
3365                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3366                         if ( card != "" ){
3367                                 print card","driver
3368                         }
3369                 }' $FILE_ASOUND_DEVICE ) )
3370         fi
3371         IFS="$ORIGINAL_IFS"
3372         get_audio_usb_data
3373         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
3374         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then
3375                 A_AUDIO_DATA[0]='Failed to Detect Sound Card!'
3376         fi
3377         temp_array=${A_AUDIO_DATA[@]}
3378         log_function_data "A_AUDIO_DATA: $temp_array"
3379
3380         eval $LOGFE
3381 }
3382 # alsa usb detection by damentz
3383
3384 get_audio_usb_data()
3385 {
3386         eval $LOGFS
3387         local usb_proc_file='' array_count='' usb_data='' usb_id='' lsusb_path='' lsusb_data=''
3388         local temp_array=''
3389         
3390         IFS=$'\n'
3391         lsusb_path=$( type -p lsusb )
3392         if [[ -n $lsusb_path ]];then
3393                 lsusb_data=$( $lsusb_path 2>/dev/null )
3394         fi
3395         log_function_data 'raw' "usb_data:\n$lsusb_data"
3396         if [[ -n $lsusb_data ]];then
3397                 # for every sound card symlink in /proc/asound - display information about it
3398                 for usb_proc_file in /proc/asound/*
3399                 do
3400                         # If the file is a symlink, and contains an important usb exclusive file: continue
3401                         if [[ -L $usb_proc_file && -e $usb_proc_file/usbid  ]]; then
3402                                 # find the contents of usbid in lsusb and print everything after the 7th word on the
3403                                 # corresponding line. Finally, strip out commas as they will change the driver :)
3404                                 usb_id=$( cat $usb_proc_file/usbid )
3405                                 usb_data=$( grep "$usb_id" <<< "$lsusb_data" )
3406                                 if [[ -n $usb_data && -n $usb_id ]];then
3407                                         usb_data=$( gawk '
3408                                         BEGIN {
3409                                                 IGNORECASE=1
3410                                                 string=""
3411                                                 separator=""
3412                                         }
3413                                         {
3414                                                 gsub( /,/, " ", $0 )
3415                                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
3416                                                 gsub(/ [ \t]+/, " ", $0)
3417                                                 for ( i=7; i<= NF; i++ ) {
3418                                                         string = string separator $i
3419                                                         separator = " "
3420                                                 }
3421                                                 if ( $2 != "" ){
3422                                                         sub(/:/,"", $4)
3423                                                         print string ",USB Audio,,," $2 "-" $4 "," $6
3424                                                 }
3425                                         }' <<< "$usb_data" )
3426                                 fi
3427                                 # this method is interesting, it shouldn't work but it does
3428                                 #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,USB Audio,," )
3429                                 # but until we learn why the above worked, I'm using this one, which is safer
3430                                 if [[ -n $usb_data ]];then
3431                                         array_count=${#A_AUDIO_DATA[@]}
3432                                         A_AUDIO_DATA[$array_count]="$usb_data"
3433                                 fi
3434                         fi
3435                 done
3436         fi
3437         IFS="$ORIGINAL_IFS"
3438         temp_array=${A_AUDIO_DATA[@]}
3439         log_function_data "A_AUDIO_DATA: $temp_array"
3440         
3441         eval $LOGFE
3442 }
3443
3444 get_audio_alsa_data()
3445 {
3446         eval $LOGFS
3447         local alsa_data='' temp_array=''
3448
3449         # now we'll get the alsa data if the file exists
3450         if [[ $B_ASOUND_VERSION_FILE == 'true' ]];then
3451                 IFS=","
3452                 A_ALSA_DATA=( $( 
3453                 gawk '
3454                         BEGIN {
3455                                 IGNORECASE=1
3456                                 alsa=""
3457                                 version=""
3458                         }
3459                         # some alsa strings have the build date in (...)
3460                         # remove trailing . and remove possible second line if compiled by user
3461                         $0 !~ /compile/ {
3462                                 gsub( /Driver | [(].*[)]|\.$/,"",$0 )
3463                                 gsub(/,/, " ", $0)
3464                                 gsub(/^ +| +$/, "", $0)
3465                                 gsub(/ [ \t]+/, " ", $0)
3466                                 sub(/Advanced Linux Sound Architecture/, "ALSA", $0)
3467                                 if ( $1 == "ALSA" ){
3468                                         alsa=$1
3469                                 }
3470                                 version=$NF
3471                                 print alsa "," version
3472                         }' $FILE_ASOUND_VERSION ) )
3473                 IFS="$ORIGINAL_IFS"
3474                 log_function_data 'cat' "$FILE_ASOUND_VERSION"
3475         fi
3476         temp_array=${A_ALSA_DATA[@]}
3477         log_function_data "A_ALSA_DATA: $temp_array"
3478         eval $LOGFE
3479 }
3480
3481 ## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text
3482 ## return value cpu core count string, this helps resolve the multi redundant lines of old style output
3483 get_cpu_core_count()
3484 {
3485         eval $LOGFS
3486         local cpu_physical_count='' cpu_core_count='' cpu_type='' cpu_alpha_count=''
3487         if [[ $B_CPUINFO_FILE == 'true' ]]; then
3488                 # load the A_CPU_TYPE_PCNT_CCNT core data array
3489                 get_cpu_ht_multicore_smp_data
3490                 ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10)
3491                 # count the number of processors given
3492                 cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]}
3493                 cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]}
3494                 cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]}
3495
3496                 # match the numberic value to an alpha value
3497                 cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
3498                 
3499                 # create array, core count integer; core count string
3500                 # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" )
3501                 A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" )
3502         elif [[ -n $BSD_TYPE ]];then
3503                 local gawk_fs=': '
3504         
3505                 if [[ $BSD_VERSION == 'openbsd' ]];then
3506                         gawk_fs='='
3507                 fi
3508                 cpu_core_count=$( gawk -F "$gawk_fs" '
3509                 # note: on openbsd can also be hw.ncpufound so exit after first
3510                 /^hw.ncpu/ {
3511                         print $NF
3512                         exit
3513                 }' <<< "$Sysctl_a_Data" )
3514                 if [[ -n $( grep -E '^[0-9]+$' <<< "$cpu_core_count" ) ]];then
3515                         cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
3516                         if [[ $cpu_core_count -gt 1 ]];then
3517                                 cpu_type='SMP'
3518                         fi
3519                 fi
3520                 cpu_physical_count=1
3521                 A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" )
3522         fi
3523         temp_array=${A_CPU_CORE_DATA[@]}
3524         log_function_data "A_CPU_CORE_DATA: $temp_array"
3525         eval $LOGFE
3526 }
3527
3528 # args: $1 - integer core count
3529 get_cpu_core_count_alpha()
3530 {
3531         eval $LOGFS
3532         local cpu_alpha_count=''
3533         
3534         case $1 in
3535                 1) cpu_alpha_count='Single';;
3536                 2) cpu_alpha_count='Dual';;
3537                 3) cpu_alpha_count='Triple';;
3538                 4) cpu_alpha_count='Quad';;
3539                 5) cpu_alpha_count='Penta';;
3540                 6) cpu_alpha_count='Hexa';;
3541                 7) cpu_alpha_count='Hepta';;
3542                 8) cpu_alpha_count='Octa';;
3543                 9) cpu_alpha_count='Ennea';;
3544                 10) cpu_alpha_count='Deca';;
3545                 *) cpu_alpha_count='Multi';;
3546         esac
3547         
3548         echo $cpu_alpha_count
3549         
3550         eval $LOGFE
3551 }
3552
3553 ## main cpu data collector
3554 get_cpu_data()
3555 {
3556         eval $LOGFS
3557         local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' temp_array=''
3558         local bsd_cpu_flags=''
3559
3560         if [[ $B_CPUINFO_FILE == 'true' ]];then
3561                 # stop script for a bit to let cpu slow down before parsing cpu /proc file
3562                 sleep $CPU_SLEEP
3563                 IFS=$'\n'
3564                 A_CPU_DATA=( $( 
3565                 gawk -F': ' '
3566                 BEGIN {
3567                         IGNORECASE=1
3568                         # need to prime nr for arm cpus, which do not have processor number output in some cases
3569                         nr = 0
3570                         count = 0
3571                         bArm = "false"
3572                 }
3573                 # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+
3574                 # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES!
3575                 # Therefore PATCH to use [ \t]+ when TESTING!
3576                 /^processor[ \t]+:/ {
3577                         gsub(/,/, " ", $NF)
3578                         gsub(/^ +| +$/, "", $NF)
3579                         if ( $NF ~ "^[0-9]+$" ) {
3580                                 nr = $NF
3581                         }
3582                         else {
3583                                 if ( $NF ~ "^ARM" ) {
3584                                         bArm = "true"
3585                                 }
3586                                 count += 1
3587                                 nr = count - 1
3588                                 cpu[nr, "model"] = $NF
3589                         }
3590                 }
3591
3592                 /^model name|^cpu\t+:/ {
3593                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
3594                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
3595                         gsub(/,/, " ", $NF)
3596                         gsub(/^ +| +$/, "", $NF)
3597                         gsub(/ [ \t]+/, " ", $NF)
3598                         cpu[nr, "model"] = $NF
3599                         if ( $NF ~ "^ARM" ) {
3600                                 bArm = "true"
3601                         }
3602                 }
3603
3604                 /^cpu MHz|^clock\t+:/ {
3605                         if (!min) {
3606                                 min = $NF
3607                         }
3608                         else {
3609                                 if ($NF < min) {
3610                                         min = $NF
3611                                 }
3612                         }
3613
3614                         if ($NF > max) {
3615                                 max = $NF
3616                         }
3617                         gsub(/MHZ/,"",$NF) ## clears out for cell cpu
3618                         gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros
3619                         cpu[nr, "speed"] = $NF
3620                 }
3621
3622                 /^cache size/ {
3623                         cpu[nr, "cache"] = $NF
3624                 }
3625
3626                 /^flags|^features/ {
3627                         cpu[nr, "flags"] = $NF
3628                         # not all ARM cpus show ARM in model name
3629                         if ( $1 ~ /^features/ ) {
3630                                 bArm = "true"
3631                         }
3632                 }
3633
3634                 /^bogomips/ {
3635                         cpu[nr, "bogomips"] = $NF
3636                 }
3637
3638                 /vendor_id/ {
3639                         gsub(/genuine|authentic/,"",$NF)
3640                         cpu[nr, "vendor"] = tolower( $NF )
3641                 }
3642
3643                 END {
3644                         #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that
3645                         for ( i = 0; i <= nr; i++ ) {
3646                                 # note: assuming bogomips for arm at 1 x clock
3647                                 # http://en.wikipedia.org/wiki/BogoMips ARM could change so watch this
3648                                 # maybe add:  && bArm == "true" but I think most of the bogomips roughly equal cpu speed if not amd/intel
3649                                 if ( cpu[i, "bogomips"] != "" && cpu[i, "speed"] == "" ) {
3650                                         cpu[i, "speed"] = cpu[i, "bogomips"]
3651                                 }
3652                                 print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] ","  cpu[nr, "vendor"] "," bArm
3653                         }
3654                         # this is / was used in inxi short output only, but when it is N/A, need to use the previous array
3655                         # value, from above, the actual speed that is, for short output, key 0.
3656                         if (!min) {
3657                                 print "N/A"
3658                                 exit
3659                         }
3660                         else {
3661                                 if (min != max) {
3662                                         printf("Min:%s%s Max:%s%s\n", min, "Mhz", max, "Mhz")
3663                                 }
3664                                 else {
3665                                         printf("%s %s\n", max, "Mhz")
3666                                 }
3667                         }
3668                 }
3669                 ' $FILE_CPUINFO ) )
3670                 IFS="$ORIGINAL_IFS"
3671                 log_function_data 'cat' "$FILE_CPUINFO"
3672         elif [[ -n $BSD_TYPE ]];then
3673                 get_cpu_data_bsd
3674         fi
3675         
3676         temp_array=${A_CPU_DATA[@]}
3677         log_function_data "A_CPU_DATA: $temp_array"
3678 #       echo ta: ${temp_array[@]}
3679         eval $LOGFE
3680 #       echo getMainCpu: ${[@]}
3681 }
3682
3683 get_cpu_data_bsd()
3684 {
3685         eval $LOGFS
3686
3687         local bsd_cpu_flags=$( get_cpu_flags_bsd )
3688         local gawk_fs=': '
3689         
3690         if [[ $BSD_VERSION == 'openbsd' ]];then
3691                 gawk_fs='='
3692         fi
3693                 
3694         IFS=$'\n'
3695         A_CPU_DATA=( $( 
3696         gawk -F "$gawk_fs" -v cpuFlags="$bsd_cpu_flags" '
3697         BEGIN {
3698                 IGNORECASE=1
3699                 cpuModel=""
3700                 cpuClock=""
3701                 cpuCache=""
3702                 cpuBogomips=""
3703                 cpuVendor=""
3704         }
3705         /^hw.model/ {
3706                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
3707                 gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
3708                 sub(//,"",$NF)
3709                 sub(/[a-z]+-core/, "", $NF )
3710                 gsub(/^ +| +$|\"/, "", $NF)
3711                 gsub(/ [ \t]+/, " ", $NF)
3712                 cpuModel=$NF
3713                 if ( cpuClock != "" ) {
3714                         exit
3715                 }
3716         }
3717         /^hw.(clock|cpuspeed)/ {
3718                 cpuClock=$NF
3719                 if ( cpuModel != "" ) {
3720                         exit
3721                 }
3722         }
3723         END {
3724                 print cpuModel "," cpuClock "," cpuCache "," cpuFlags "," cpuBogomips ","  cpuVendor
3725                 print "N/A"
3726         }' <<< "$Sysctl_a_Data" ) )
3727         IFS="$ORIGINAL_IFS"
3728         
3729         eval $LOGFE
3730 }
3731
3732 get_cpu_flags_bsd()
3733 {
3734         eval $LOGFS
3735         
3736         local cpu_flags=$( gawk -F '=' '
3737         BEGIN {
3738                 IGNORECASE=1
3739                 cpuFlags=""
3740         }
3741         /^CPU:/ {
3742                 while ( getline && !/memory/  ) {
3743                         if ( $1 ~ /Features/ ) {
3744                                 # clean up odd stuff like <b23>
3745                                 gsub(/<[a-z0-9]+>/,"", $2)
3746                                 # all the flags are contained within < ... > on freebsd at least
3747                                 gsub(/.*<|>.*/,"", $2)
3748                                 gsub(/,/," ", $2)
3749                                 cpuFlags = cpuFlags " " $2
3750                         }
3751                 }
3752                 cpuFlags=tolower(cpuFlags)
3753                 print cpuFlags
3754                 exit
3755         }' <<< "$Dmesg_Boot_Data" )
3756         
3757         echo $cpu_flags
3758         log_function_data "$cpu_flags"
3759         eval $LOGFE
3760 }
3761
3762 ## this is for counting processors and finding HT types
3763 get_cpu_ht_multicore_smp_data()
3764 {
3765         eval $LOGFS
3766         # in /proc/cpuinfo
3767         local temp_array=''
3768         
3769         # note: known bug with xeon intel, they show a_core_id/physical_id as 0 for ht 4 core
3770         if [[ $B_CPUINFO_FILE == 'true' ]]; then
3771                 A_CPU_TYPE_PCNT_CCNT=( $(
3772                 gawk '
3773                 BEGIN {
3774                         FS=": "
3775                         IGNORECASE = 1
3776                         num_of_cores = 0
3777                         num_of_processors = 0
3778                         num_of_physical_cpus = 0
3779                         cpu_core_count = 0
3780                         siblings = 0
3781                         # these 3 arrays cannot be declared because that sets the first element
3782                         # but leaving this here so that we avoid doing that in the future
3783                         # a_core_id = ""
3784                         # a_processor_id = ""
3785                         # a_physical_id = ""
3786                         cpu_type = "-"
3787                         # note: we need separate iterators because some cpuinfo data has only
3788                         # processor, no core id or phys id
3789                         proc_iter = 0
3790                         core_iter = "" # set from actual NF data
3791                         phys_iter = "" # set from actual NF data
3792                         # needed to handle arm cpu, no processor number cases
3793                         arm_count = 0
3794                         nr = 0
3795                         bArm = "false"
3796                         bXeon = "false"
3797                 }
3798                 # hack to handle xeons which can have buggy /proc/cpuinfo files
3799                 /^model name/ && ( $0 ~ /Xeon/ ) {
3800                         bXeon = "true"
3801                 }
3802                 # only do this once since sibling count does not change. 
3803                 /^siblings/ && ( bXeon == "true" ) && ( siblings == 0 ) {
3804                         gsub(/[^0-9]/,"",$NF)
3805                         if ( $NF != "" ) {
3806                                 siblings = $NF
3807                         }
3808                 }
3809                 # array of logical processors, both HT and physical
3810                 
3811                 /^processor/ {
3812                         gsub(/,/, " ", $NF)
3813                         gsub(/^ +| +$/, "", $NF)
3814                         if ( $NF ~ "^[0-9]+$" ) {
3815                                 a_processor_id[proc_iter] = $NF
3816                                 proc_iter++
3817                         }
3818                         else {
3819                                 # note, for dual core, this can be off by one because the first
3820                                 # line says: Processor : Arm.. but subsequent say: processor : 0 and so on as usual
3821                                 if ( $NF ~ "^ARM" ) {
3822                                         bArm = "true"
3823                                 }
3824                                 arm_count += 1
3825                                 nr = arm_count - 1
3826                                 # note: do not iterate because new ARM syntax puts cpu in processsor : 0 syntax
3827                                 a_processor_id[proc_iter] = nr
3828                         }
3829                 }
3830                 
3831                 # array of physical cpu ids, note, this will be unset for vm cpus in many cases
3832                 # because they have no physical cpu, so we cannot assume this will be here.
3833                 /^physical/ {
3834                         phys_iter = $NF
3835                         a_physical_id[phys_iter] = $NF
3836                 }
3837                 # array of core ids, again, here we may have HT, so we need to create an array of the
3838                 # actual core ids. As With physical, we cannot assume this will be here in a vm
3839                 /^core id/ {
3840                         core_iter = $NF
3841                         a_core_id[core_iter] = $NF
3842                 }
3843                 # this will be used to fix an intel glitch if needed, cause, intel
3844                 # sometimes reports core id as the same number for each core, 
3845                 # so if cpu cores shows greater value than number of cores, use this. 
3846                 /^cpu cores/ {
3847                         cpu_core_count = $NF
3848                 }
3849                 END {
3850                         ##      Look thru the array and filter same numbers.
3851                         ##      only unique numbers required
3852                         ##      this is to get an accurate count
3853                         ##      we are only concerned with array length
3854                         i = 0
3855                         ## count unique processors ##
3856                         # note, this fails for intel cpus at times
3857                         for ( i in a_processor_id ) {
3858                                 num_of_processors++
3859                         }
3860                         i = 0
3861                         ## count unique physical cpus ##
3862                         for ( i in a_physical_id ) {
3863                                 num_of_physical_cpus++
3864                         }
3865                         
3866                         i = 0
3867                         ## count unique cores ##
3868                         for ( i in a_core_id ) {
3869                                 num_of_cores++
3870                         }
3871                         # xeon may show wrong core / physical id count, if it does, fix it. A xeon
3872                         # may show a repeated core id : 0 which gives a fake num_of_cores=1
3873                         if ( bXeon == "true" && num_of_cores == 1 && siblings > 1 ) {
3874                                 num_of_cores = siblings/2
3875                         }
3876                         # final check, override the num of cores value if it clearly is wrong
3877                         # and use the raw core count and synthesize the total instead of real count
3878                         if ( ( num_of_cores == 0 ) && ( cpu_core_count * num_of_physical_cpus > 1 ) ) {
3879                                 num_of_cores = cpu_core_count * num_of_physical_cpus
3880                         }
3881                         # last check, seeing some intel cpus and vms with intel cpus that do not show any
3882                         # core id data at all, or siblings.
3883                         if ( num_of_cores == 0 && num_of_processors > 0 ) {
3884                                 num_of_cores = num_of_processors
3885                         }
3886                         # ARM/vm cpu fix, if no physical or core found, use count of 1 instead
3887                         if ( num_of_physical_cpus == 0 ) {
3888                                 num_of_physical_cpus = 1
3889                         }
3890 #                       print "NoCpu: " num_of_physical_cpus
3891 #                       print "NoCores: " num_of_cores
3892 #                       print "NoProc:" num_of_processors
3893 #                       print "CpuCoreCount:" cpu_core_count
3894                         ####################################################################
3895                         #                               algorithm
3896                         # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT)
3897                         # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
3898                         # if > 1 processor && processor ids (physical id) > 1 then Multiple Processors (SMP)
3899                         # if = 1 processor then single core/processor Uni-Processor (UP)
3900                         if ( num_of_processors > 1 || ( bXeon == "true" && siblings > 0 ) ) {
3901                                 # non-multicore HT
3902                                 if ( num_of_processors == (num_of_cores * 2) ) {
3903                                         cpu_type = cpu_type "HT-"
3904                                 }
3905                                 else if ( bXeon == "true" && siblings > 1 ) {
3906                                         cpu_type = cpu_type "HT-"
3907                                 }
3908                                 # non-HT multi-core or HT multi-core
3909                                 if (( num_of_processors == num_of_cores) || ( num_of_physical_cpus < num_of_cores)) {
3910                                         cpu_type = cpu_type "MCP-"
3911                                 }
3912                                 # >1 cpu sockets active
3913                                 if ( num_of_physical_cpus > 1 ) {
3914                                         cpu_type = cpu_type "SMP-"
3915                                 }
3916                         } 
3917                         else {
3918                                 cpu_type = cpu_type "UP-"
3919                         }                       
3920                         
3921                         print cpu_type " " num_of_physical_cpus " " num_of_cores 
3922                 }
3923                 ' $FILE_CPUINFO ) )
3924         fi
3925         temp_array=${A_CPU_TYPE_PCNT_CCNT[@]}
3926         log_function_data "A_CPU_TYPE_PCNT_CCNT: $temp_array"
3927         eval $LOGFE
3928 }
3929
3930 # Detect desktop environment in use, initial rough logic from: compiz-check
3931 # http://forlong.blogage.de/entries/pages/Compiz-Check
3932 # NOTE $XDG_CURRENT_DESKTOP envvar is not reliable, but it shows certain desktops better.
3933 # most desktops are not using it as of 2014-01-13 (KDE, UNITY, LXDE. Not Gnome)
3934 get_desktop_environment()
3935 {
3936         eval $LOGFS
3937         
3938         # set the default, this function only runs in X, if null, don't print data out
3939         local desktop_environment='' xprop_root=''
3940         local version='' version_data='' toolkit=''
3941
3942         # works on 4, assume 5 will id the same, why not, no need to update in future
3943         # KDE_SESSION_VERSION is the integer version of the desktop
3944         if [[ $XDG_CURRENT_DESKTOP == 'KDE' || -n $KDE_SESSION_VERSION ]]; then
3945                 # note the command is actually like, kded4 --version, so we construct it
3946                 version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
3947                 version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
3948                 if [[ -z $version ]];then
3949                         version=$KDE_SESSION_VERSION
3950                 fi
3951                 if [[ $B_EXTRA_DATA == 'true' ]];then
3952                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3953                         if [[ -n $toolkit ]];then
3954                                 version="$version (Qt $toolkit)"
3955                         fi
3956                 fi
3957                 desktop_environment="KDE"
3958         # KDE_FULL_SESSION property is only available since KDE 3.5.5.
3959         # src: http://humanreadable.nfshost.com/files/startkde
3960         elif [[ $KDE_FULL_SESSION == 'true' ]]; then
3961                 version_data=$( kded --version 2>/dev/null )
3962                 version=$( grep -si '^KDE:' <<< "$version_data" | gawk '{print $2}' )
3963                 # version=$( get_de_app_version 'kded' '^KDE:' '2' )
3964                 if [[ -z $version ]];then
3965                         version='3.5'
3966                 fi
3967                 if [[ $B_EXTRA_DATA == 'true' ]];then
3968                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3969                         if [[ -n $toolkit ]];then
3970                                 version="$version (Qt $toolkit)"
3971                         fi
3972                 fi
3973                 desktop_environment="KDE"
3974         elif [[ $XDG_CURRENT_DESKTOP == 'Unity' ]];then
3975                 version=$( get_de_app_version 'unity' '^unity' '2' )
3976                 # not certain cinn will always have version, so keep output right if not
3977                 if [[ -n $version ]];then
3978                         version="$version "
3979                 fi
3980                 if [[ $B_EXTRA_DATA == 'true' ]];then
3981                         toolkit=$( get_de_gtk_data )
3982                         if [[ -n $toolkit ]];then
3983                                 version="${version}(Gtk ${toolkit})"
3984                         fi
3985                 fi
3986                 desktop_environment="Unity"
3987         fi
3988         # did we find it? If not, start the xprop tests
3989         if [[ -z $desktop_environment ]];then
3990                 if [[ -n $( type -p xprop ) ]];then
3991                         xprop_root="$( xprop -root 2>/dev/null )"
3992                 fi
3993                 # note that cinnamon split from gnome, and and can now be id'ed via xprop,
3994                 # but it will still trigger the next gnome true case, so this needs to go before gnome test
3995                 # eventually this needs to be better organized so all the xprop tests are in the same
3996                 # section, but this is good enough for now.
3997                 if [[ -n $xprop_root && -n $( grep -is '^_MUFFIN' <<< "$xprop_root" ) ]];then
3998                         version=$( get_de_app_version 'cinnamon' '^cinnamon' '2' )
3999                         # not certain cinn will always have version, so keep output right if not
4000                         if [[ -n $version ]];then
4001                                 version="$version "
4002                         fi
4003                         if [[ $B_EXTRA_DATA == 'true' ]];then
4004                                 toolkit=$( get_de_gtk_data )
4005                                 if [[ -n $toolkit ]];then
4006                                         version="${version}(Gtk ${toolkit})"
4007                                 fi
4008                         fi
4009                         desktop_environment="Cinnamon"
4010                 elif [[ -n $xprop_root && -n $( grep -is '^_MARCO' <<< "$xprop_root" ) ]];then
4011                         version=$( get_de_app_version 'mate-about' '^MATE[[:space:]]DESKTOP' 'NF' )
4012                         # not certain cinn/mate will always have version, so keep output right if not
4013                         if [[ -n $version ]];then
4014                                 version="$version "
4015                         fi
4016                         if [[ $B_EXTRA_DATA == 'true' ]];then
4017                                 toolkit=$( get_de_gtk_data )
4018                                 if [[ -n $toolkit ]];then
4019                                         version="${version}(Gtk ${toolkit})"
4020                                 fi
4021                         fi
4022                         desktop_environment="MATE"
4023                 # note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out
4024                 # https://bugzilla.gnome.org/show_bug.cgi?id=542880
4025                 elif [[ -n $GNOME_DESKTOP_SESSION_ID ]]; then
4026                         if [[ -n $( type -p gnome-shell ) ]];then
4027                                 version=$( get_de_app_version 'gnome-shell' 'gnome' '3' )
4028                         elif [[ -n $( type -p gnome-about ) ]];then
4029                                 version=$( get_de_app_version 'gnome-about' 'gnome' '3' )
4030                         fi
4031                         if [[ $B_EXTRA_DATA == 'true' ]];then
4032                                 toolkit=$( get_de_gtk_data )
4033                                 if [[ -n $toolkit ]];then
4034                                         version="$version (Gtk $toolkit)"
4035                                 fi
4036                         fi
4037                         desktop_environment="Gnome"
4038                 fi
4039                 if [[ -z $desktop_environment ]];then
4040                 # now that the primary ones have been handled, next is to find the ones with unique
4041                 # xprop detections possible
4042                         if [[ -n $xprop_root ]];then
4043                                 # String: "This is xfdesktop version 4.2.12"
4044                                 # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10)
4045                                 if [[ -n $( grep -Eis '\"xfce4\"' <<< "$xprop_root" ) ]];then
4046                                         version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
4047                                         # arch linux reports null, so use alternate if null
4048                                         if [[ -z $version ]];then
4049                                                 version=$( get_de_app_version 'xfce4-panel' '^xfce4-panel' '2' )
4050                                                 if [[ -z $version ]];then
4051                                                         version='4'
4052                                                 fi
4053                                         fi
4054                                         if [[ $B_EXTRA_DATA == 'true' ]];then
4055                                                 toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
4056                                                 if [[ -n $toolkit ]];then
4057                                                         version="$version (Gtk $toolkit)"
4058                                                 fi
4059                                         fi
4060                                         desktop_environment="Xfce"
4061                                 # when 5 is released, the string may need updating
4062                                 elif [[ -n $( grep -is '\"xfce5\"' <<< "$xprop_root" ) ]];then
4063                                         version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
4064                                         # arch linux reports null, so use alternate if null
4065                                         if [[ -z $version ]];then
4066                                                 version=$( get_de_app_version 'xfce5-panel' '^xfce5-panel' '2' )
4067                                                 if [[ -z $version ]];then
4068                                                         version='5'
4069                                                 fi
4070                                         fi
4071                                         if [[ $B_EXTRA_DATA == 'true' ]];then
4072                                                 toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
4073                                                 if [[ -n $toolkit ]];then
4074                                                         version="$version (Gtk $toolkit)"
4075                                                 fi
4076                                         fi
4077                                         desktop_environment="Xfce"
4078                                 elif [[ -n $( grep -is 'BLACKBOX_PID' <<< "$xprop_root" ) ]];then
4079                                         if [[ -n $( grep -is 'fluxbox' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4080                                                 version=$( get_de_app_version 'fluxbox' '^fluxbox' '2' )
4081                                                 desktop_environment='Fluxbox'
4082                                         else
4083                                                 desktop_environment='Blackbox'
4084                                         fi
4085                                 elif [[ -n $( grep -is 'OPENBOX_PID' <<< "$xprop_root" ) ]];then
4086                                         # note: openbox-lxde --version may be present, but returns openbox data
4087                                         version=$( get_de_app_version 'openbox' '^openbox' '2' )
4088                                         if [[ $XDG_CURRENT_DESKTOP == 'LXDE' || \
4089                                                         -n $( grep -is 'lxde' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4090                                                 if [[ -n $version ]];then
4091                                                         version="(Openbox $version)"
4092                                                 fi
4093                                                 desktop_environment='LXDE'
4094                                         elif [[ -n $( grep -is 'razor-desktop' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4095                                                 if [[ -n $version ]];then
4096                                                         version="(Openbox $version)"
4097                                                 fi
4098                                                 desktop_environment='Razor-QT'
4099                                         else
4100                                                 desktop_environment='Openbox'
4101                                         fi
4102                                 elif [[ -n $( grep -is 'ICEWM' <<< "$xprop_root" ) ]];then
4103                                         version=$( get_de_app_version 'icewm' '^icewm' '2' )
4104                                         desktop_environment='IceWM'
4105                                 elif [[ -n $( grep -is 'ENLIGHTENMENT' <<< "$xprop_root" ) ]];then
4106                                         # no -v or --version but version is in xprop -root
4107                                         # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898"
4108                                         version=$( grep -is 'ENLIGHTENMENT_VERSION' <<< "$xprop_root" | cut -d '"' -f 2 | gawk '{print $2}' )
4109                                         desktop_environment='Enlightenment'
4110                                 elif [[ -n $( grep -is '^I3_' <<< "$xprop_root" ) ]];then
4111                                         version=$( get_de_app_version 'i3' '^i3' '3' )
4112                                         desktop_environment='i3'
4113                                 elif [[ -n $( grep -is 'WINDOWMAKER' <<< "$xprop_root" ) ]];then
4114                                         version=$( get_de_app_version 'wmaker' '^Window[[:space:]]*Maker' 'NF' )
4115                                         if [[ -n $version ]];then
4116                                                 version="$version "
4117                                         fi
4118                                         desktop_environment="WindowMaker"
4119                                 elif [[ -n $( grep -is '^_WM2' <<< "$xprop_root" ) ]];then
4120                                         # note; there isn't actually a wm2 version available but error handling should cover it and return null
4121                                         # maybe one day they will add it?
4122                                         version=$( get_de_app_version 'wm2' '^wm2' 'NF' )
4123                                         # not certain will always have version, so keep output right if not
4124                                         if [[ -n $version ]];then
4125                                                 version="$version "
4126                                         fi
4127                                         desktop_environment="WM2"
4128                                 elif [[ -n $( grep -is 'herbstluftwm' <<< "$xprop_root" ) ]];then
4129                                         version=$( get_de_app_version 'herbstluftwm' '^herbstluftwm' 'NF' )
4130                                         if [[ -n $version ]];then
4131                                                 version="$version "
4132                                         fi
4133                                         desktop_environment="herbstluftwm"
4134                                 fi
4135                         fi
4136                         # a few manual hacks for things that don't id with xprop, these are just good guesses
4137                         # note that gawk is going to exit after first occurance of search string, so no need for extra
4138                         if [[ -z $desktop_environment ]];then
4139                                 if [[ -n $( grep -is 'fvwm-crystal'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4140                                         version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
4141                                         desktop_environment='FVWM-Crystal'
4142                                 elif [[ -n $( grep -is 'fvwm'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4143                                         version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
4144                                         desktop_environment='FVWM'
4145                                 elif [[ -n $( grep -is 'pekwm'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4146                                         version=$( get_de_app_version 'pekwm' '^pekwm' '3' )
4147                                         desktop_environment='pekwm'
4148                                 elif [[ -n $( grep -is 'awesome' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4149                                         version=$( get_de_app_version 'awesome' '^awesome' '2' )
4150                                         desktop_environment='Awesome'
4151                                 elif [[ -n $( grep -is 'scrotwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4152                                         version=$( get_de_app_version 'scrotwm' '^welcome.*scrotwm' '4' )
4153                                         desktop_environment='Scrotwm' # no --version for this one
4154                                 elif [[ -n $( grep -is 'spectrwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4155                                         version=$( get_de_app_version 'spectrwm' '^spectrwm.*welcome.*spectrwm' '5' )
4156                                         desktop_environment='Spectrwm' # no --version for this one
4157                                 elif [[ -n $( grep -Eis '([[:space:]]|/)twm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4158                                         desktop_environment='Twm' # no --version for this one
4159                                 elif [[ -n $( grep -Eis '([[:space:]]|/)dwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4160                                         version=$( get_de_app_version 'dwm' '^dwm' '1' )
4161                                         desktop_environment='dwm'
4162                                 elif [[ -n $( grep -is 'wmii2' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4163                                         version=$( get_de_app_version 'wmii2' '^wmii2' '1' )
4164                                         desktop_environment='wmii2'
4165                                 # note: in debian at least, wmii is actuall wmii3
4166                                 elif [[ -n $( grep -is 'wmii' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4167                                         version=$( get_de_app_version 'wmii' '^wmii' '1' )
4168                                         desktop_environment='wmii'
4169                                 elif [[ -n $( grep -Eis '([[:space:]]|/)jwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4170                                         version=$( get_de_app_version 'jwm' '^jwm' '2' )
4171                                         desktop_environment='JWM'
4172                                 fi
4173                         fi
4174                 fi
4175         fi
4176         if [[ -n $version ]];then
4177                 version=" $version"
4178         fi
4179         echo "$desktop_environment${version}"
4180         eval $LOGFE
4181 }
4182
4183 # note: gawk doesn't support white spaces in search string, gave errors, so use [[:space:]] instead
4184 # args: $1 - desktop/app command for --version; $2 - search string; $3 - gawk print number
4185 get_de_app_version()
4186 {
4187         local version_data='' version='' get_version='--version' 
4188         
4189         # mate-about -v = MATE Desktop Environment 1.4.0
4190         case $1 in
4191                 dwm|jwm|mate-about|wmii|wmii2)
4192                         get_version='-v'
4193                         ;;
4194                 epoch)
4195                         get_version='version'
4196                         ;;
4197         esac
4198         
4199         case $1 in
4200                 # note, some wm/apps send version info to stderr instead of stdout
4201                 dwm|ksh|scrotwm|spectrwm)
4202                         version_data="$( $1 $get_version 2>&1 )"
4203                         ;;
4204                 csh)
4205                         version_data="$( tcsh $get_version 2>/dev/null )"
4206                         ;;
4207                 # quick debian/buntu hack until I find a universal way to get version for these
4208                 dash)
4209                         if [[ -n $( type -p dpkg ) ]];then
4210                                 version_data="$( dpkg -l $1 2>/dev/null )"
4211                         fi
4212                         ;;
4213                 *)
4214                         version_data="$( $1 $get_version 2>/dev/null )"
4215                         ;;
4216         esac
4217         
4218         if [[ -n $version_data ]];then
4219                 version=$( gawk '
4220                 BEGIN {
4221                         IGNORECASE=1
4222                 }
4223                 /'$2'/ {
4224                         # sample: dwm-5.8.2, Â©.. etc, why no space? who knows. Also get rid of v in number string
4225                         # xfce, and other, output has , in it, so dump all commas and parentheses
4226                         gsub(/(,|dwm-|wmii2-|wmii-|v|V|\(|\))/, "",$'$3') 
4227                         print $'$3'
4228                         exit # quit after first match prints
4229                 }' <<< "$version_data" )
4230         fi
4231         echo $version
4232 }
4233
4234 get_desktop_extra_data()
4235 {
4236         eval $LOGFS
4237         local de_data=$( ps -A | gawk '
4238         BEGIN {
4239                 IGNORECASE=1
4240                 desktops=""
4241                 separator=""
4242         }
4243         /(gnome-shell|gnome-panel|kicker|lxpanel|mate-panel|plasma-desktop|xfce4-panel)$/ {
4244                 # only one entry per type, can be multiple
4245                 if ( desktops !~ $NF ) {
4246                         desktops = desktops separator $NF
4247                         separator = ","
4248                 }
4249         }
4250         END {
4251                 print desktops
4252         }
4253         ' )
4254         echo $de_data
4255         
4256         eval $LOGFE
4257 }
4258
4259 get_de_gtk_data()
4260 {
4261         eval $LOGFS
4262         
4263         local toolkit=''
4264         
4265         # this is a hack, and has to be changed with every toolkit version change, and only dev systems
4266         # have this installed, but it's a cross distro command so let's test it first
4267         if [[ -n $( type -p pkg-config ) ]];then
4268                 toolkit=$( pkg-config --modversion gtk+-4.0 2>/dev/null )
4269                 # note: opensuse gets null output here, we need the command to get version and output sample
4270                 if [[ -z $toolkit ]];then
4271                         toolkit=$( pkg-config --modversion gtk+-3.0 2>/dev/null )
4272                 fi
4273                 if [[ -z $toolkit ]];then
4274                         toolkit=$( pkg-config --modversion gtk+-2.0 2>/dev/null )
4275                 fi
4276         fi
4277         # now let's go to more specific version tests, this will never cover everything and that's fine.
4278         if [[ -z $toolkit ]];then
4279                 # we'll try some known package managers next. dpkg will handle a lot of distros 
4280                 # this is the most likely order as of: 2014-01-13. Not going to try to support all package managers
4281                 # too much work, just the very biggest ones.
4282                 if [[ -n $( type -p dpkg ) ]];then
4283                         toolkit=$( dpkg -s libgtk-3-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4284                         if [[ -z $toolkit ]];then
4285                                 toolkit=$( dpkg -s libgtk2.0-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4286                         fi
4287                         # just guessing on gkt 4 package name
4288                         if [[ -z $toolkit ]];then
4289                                 toolkit=$( dpkg -s libgtk-4-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4290                         fi
4291                 elif [[ -n $( type -p pacman ) ]];then
4292                         toolkit=$(  pacman -Qi gtk3 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4293                         if [[ -z $toolkit ]];then
4294                                 toolkit=$( pacman -Qi gtk2 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4295                         fi
4296                 fi
4297         fi
4298         echo $toolkit
4299         
4300         eval $LOGFE
4301 }
4302
4303 # see which dm has started if any
4304 get_display_manager()
4305 {
4306         eval $LOGFS
4307         # ldm - LTSP display manager
4308         local dm_id_list='entranced.pid entrance/entranced.pid gdm.pid gdm3.pid kdm.pid ldm.pid lightdm.pid lxdm.pid mdm.pid nodm.pid slim.lock tint2.pid wdm.pid xdm.pid' 
4309         local dm_id='' dm='' separator=''
4310         # note we don't need to filter grep if we do it this way
4311         local x_is_running=$( grep '/usr.*/X' <<< "$Ps_aux_Data" | grep -iv '/Xprt' )
4312
4313         for dm_id in $dm_id_list
4314         do
4315                 if [[ -e /var/run/$dm_id || -e /run/$dm_id ]];then
4316                         # just on the off chance that two dms are running, good info to have in that case, if possible
4317                         dm=$dm$separator$( basename $dm_id | cut -d '.' -f 1 )
4318                         separator=','
4319                 fi
4320         done
4321         # might add this in, but the rate of new dm's makes it more likely it's an unknown dm, so
4322         # we'll keep output to N/A
4323         if [[ -n $x_is_running && -z $dm ]];then
4324                 if [[ -n $( grep 'startx$' <<< "$Ps_aux_Data" ) ]];then
4325                         dm='(startx)'
4326                 fi
4327         fi
4328         echo $dm
4329
4330         log_function_data "display manager: $dm"
4331
4332         eval $LOGFE
4333 }
4334
4335 # for more on distro id, please reference this python thread: http://bugs.python.org/issue1322
4336 ## return distro name/id if found
4337 get_distro_data()
4338 {
4339         eval $LOGFS
4340         local i='' j='' distro='' distro_file='' a_distro_glob='' temp_array=''
4341         
4342         # may need modification if archbsd / debian can be id'ed with /etc files
4343         if [[ -n $BSD_TYPE ]];then
4344                 distro=$( uname -sr )
4345                 echo "$distro"
4346                 log_function_data "distro: $distro"
4347                 eval $LOGFE
4348                 return 0
4349         fi
4350
4351         # get the wild carded array of release/version /etc files if present
4352         shopt -s nullglob
4353         cd /etc
4354         # note: always exceptions, so wild card after release/version: /etc/lsb-release-crunchbang
4355         # wait to handle since crunchbang file is one of the few in the world that uses this method
4356         a_distro_glob=(*[-_]{release,version})
4357         cd "$OLDPWD"
4358         shopt -u nullglob
4359         
4360         temp_array=${a_distro_glob[@]}
4361         log_function_data "A_GLX_DATA: $temp_array"
4362
4363         if [[ ${#a_distro_glob[@]} -eq 1 ]];then
4364                 distro_file="${a_distro_glob}"
4365         # use the file if it's in the known good lists
4366         elif [[ ${#a_distro_glob[@]} -gt 1 ]];then
4367                 for i in $DISTROS_DERIVED $DISTROS_PRIMARY
4368                 do
4369                         # Only echo works with ${var[@]}, not print_screen_output() or script_debugger()
4370                         # This is a known bug, search for the word "strange" inside comments
4371                         # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'"
4372                         if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then
4373                                 # Now lets see if the distro file is in the known-good working-lsb-list
4374                                 # if so, use lsb-release, if not, then just use the found file
4375                                 # this is for only those distro's with self named release/version files
4376                                 # because Mint does not use such, it must be done as below 
4377                                 ## this if statement requires the spaces and * as it is, else it won't work
4378                                 ##
4379                                 if [[ " $DISTROS_LSB_GOOD " == *" ${i} "* ]] && [[ $B_LSB_FILE == 'true' ]];then
4380                                         distro_file='lsb-release'
4381                                 elif [[ " $DISTROS_OS_RELEASE_GOOD " == *" ${i} "* ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
4382                                         distro_file='os-release'
4383                                 else
4384                                         distro_file="${i}"
4385                                 fi
4386                                 break
4387                         fi
4388                 done
4389         fi
4390         log_function_data "distro_file: $distro_file"
4391         # first test for the legacy antiX distro id file
4392         if [[ -e /etc/antiX ]];then
4393                 distro="$( grep -Eoi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )"
4394         # this handles case where only one release/version file was found, and it's lsb-release. This would
4395         # never apply for ubuntu or debian, which will filter down to the following conditions. In general
4396         # if there's a specific distro release file available, that's to be preferred, but this is a good backup.
4397         elif [[ -n $distro_file && $B_LSB_FILE == 'true' && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then
4398                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4399         elif [[ $distro_file == 'lsb-release' ]];then
4400                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4401         elif [[ $distro_file == 'os-release' ]];then
4402                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
4403         # then if the distro id file was found and it's not in the exluded primary distro file list, read it
4404         elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then
4405                 # new opensuse uses os-release, but older ones may have a similar syntax, so just use the first line
4406                 if [[ $distro_file == 'SuSE-release' ]];then
4407                         # leaving off extra data since all new suse have it, in os-release, this file has line breaks, like os-release
4408                         # but in case we  want it, it's: CODENAME = Mantis  | VERSION = 12.2 
4409                         # for now, just take first occurance, which should be the first line, which does not use a variable type format
4410                         distro=$( grep -i -m 1 'suse' /etc/$distro_file )
4411                 else
4412                         distro=$( remove_erroneous_chars "/etc/$distro_file" )
4413                 fi
4414         # otherwise try  the default debian/ubuntu /etc/issue file
4415         elif [[ -f /etc/issue ]];then
4416                 # lsb gives more manageable and accurate output than issue, but mint should use issue for now
4417                 # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]]
4418                 if [[ $B_LSB_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
4419                         distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4420                 else
4421                         distro=$( gawk '
4422                         BEGIN {
4423                                 RS=""
4424                         }
4425                         {
4426                                 gsub(/\\[a-z]/, "")
4427                                 gsub(/,/, " ")
4428                                 gsub(/^ +| +$/, "")
4429                                 gsub(/ [ \t]+/, " ")
4430                                 print
4431                         }' /etc/issue )
4432                         
4433                         # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted
4434                         # only older arch installs that have not been updated should have this fallback required, new ones use
4435                         # os-release
4436                         if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then
4437                                 distro='Arch Linux'
4438                         fi
4439                 fi
4440         fi
4441         
4442         if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then
4443                 distro="${RED}/etc/${distro_file} corrupted, use -% to override${NORMAL}"
4444         fi
4445         ## note: would like to actually understand the method even if it's not used
4446         # : ${distro:=Unknown distro o_O}
4447         ## test for /etc/lsb-release as a backup in case of failure, in cases where > one version/release file
4448         ## were found but the above resulted in null distro value
4449         if [[ -z $distro ]] && [[ $B_LSB_FILE == 'true' ]];then
4450                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4451         fi
4452         if [[ -z $distro ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
4453                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
4454         fi
4455         # now some final null tries
4456         if [[ -z $distro ]];then
4457                 # if the file was null but present, which can happen in some cases, then use the file name itself to 
4458                 # set the distro value. Why say unknown if we have a pretty good idea, after all?
4459                 if [[ -n $distro_file ]] && [[ " $DISTROS_DERIVED $DISTROS_PRIMARY " == *" $distro_file "* ]];then
4460                         distro=$( sed $SED_RX -e 's/[-_]//' -e 's/(release|version)//' <<< $distro_file | sed $SED_RX 's/^([a-z])/\u\1/' )
4461                 fi
4462                 ## finally, if all else has failed, give up
4463                 if [[ -z $distro ]];then
4464                         distro='unknown'
4465                 fi
4466         fi
4467         # final step cleanup of unwanted information
4468         # opensuse has the x86 etc type string in names, not needed as redundant since -S already shows that
4469         distro=$( gawk '
4470         BEGIN {
4471                 IGNORECASE=1
4472         }
4473         {
4474                 sub(/ *\(*(x86_64|i486|i586|i686|686|586|486)\)*/, "", $0)
4475                 print $0
4476         }' <<< $distro )
4477         echo "$distro"
4478         log_function_data "distro: $distro"
4479         eval $LOGFE
4480 }
4481
4482 # args: $1 - lsb-file/lsb-app/os-release-file
4483 get_distro_lsb_os_release_data()
4484 {
4485         eval $LOGFS
4486         local distro=''
4487         
4488         case $1 in
4489                 lsb-file)
4490                         if [[ $B_LSB_FILE == 'true' ]];then
4491                                 distro=$( gawk -F '=' '
4492                                 BEGIN {
4493                                         IGNORECASE=1
4494                                 }
4495                                 # clean out unwanted characters
4496                                 { 
4497                                         gsub(/\\|\"|[:\47]/,"", $0 )
4498                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4499                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4500                                 }
4501                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
4502                                 /^DISTRIB_ID/ {
4503                                         # this is needed because grep for "arch" is too loose to be safe
4504                                         if ( $2 == "arch" ) {
4505                                                 distroId = "Arch Linux"
4506                                         }
4507                                         else if ( $2 != "n/a" ) {
4508                                                 distroId = $2 " "
4509                                         }
4510                                 }
4511                                 /^DISTRIB_RELEASE/ {
4512                                         if ( $2 != "n/a" ) {
4513                                                 distroRelease = $2 " "
4514                                         }
4515                                 }
4516                                 /^DISTRIB_CODENAME/ {
4517                                         if ( $2 != "n/a" ) {
4518                                                 distroCodename = $2 " "
4519                                         }
4520                                 }
4521                                 # sometimes some distros cannot do their lsb-release files correctly, so here is
4522                                 # one last chance to get it right.
4523                                 /^DISTRIB_DESCRIPTION/ {
4524                                         if ( $2 != "n/a" ) {
4525                                                 distroDescription = $2
4526                                         }
4527                                 }
4528                                 END {
4529                                         fullString=""
4530                                         if ( distroId == "" && distroRelease == "" && distroCodename == "" && distroDescription != "" ){
4531                                                 fullString = distroDescription
4532                                         }
4533                                         else {
4534                                                 fullString = distroId distroRelease distroCodename
4535                                         }
4536                                         print fullString
4537                                 }
4538                                 ' $FILE_LSB_RELEASE )
4539                                 log_function_data 'cat' "$FILE_LSB_RELEASE"
4540                         fi
4541                         ;;
4542                 lsb-app)
4543                         # this is HORRIBLY slow, not using
4544                         if [[  -n $( type -p lsb_release ) ]];then
4545                                 distro=$( echo "$( lsb_release -irc )" | gawk -F ':' '
4546                                 BEGIN { 
4547                                         IGNORECASE=1 
4548                                 }
4549                                 # clean out unwanted characters
4550                                 { 
4551                                         gsub(/\\|\"|[:\47]/,"", $0 )
4552                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4553                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4554                                 }
4555                                 /^Distributor ID/ {
4556                                         distroId = $2
4557                                 }
4558                                 /^Release/ {
4559                                         distroRelease = $2
4560                                 }
4561                                 /^Codename/ {
4562                                         distroCodename = $2
4563                                 }
4564                                 END {
4565                                         print distroId " " distroRelease " (" distroCodename ")"
4566                                 }' )
4567                         fi
4568                         ;;
4569                 os-release-file)
4570                         if [[ $B_OS_RELEASE_FILE == 'true' ]];then
4571                                 distro=$( gawk -F '=' '
4572                                 BEGIN {
4573                                         IGNORECASE=1
4574                                         prettyName=""
4575                                         regularName=""
4576                                         versionName=""
4577                                         versionId=""
4578                                         distroName=""
4579                                 }
4580                                 # clean out unwanted characters
4581                                 { 
4582                                         gsub(/\\|\"|[:\47]/,"", $0 )
4583                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4584                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4585                                 }
4586                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
4587                                 /^PRETTY_NAME/ {
4588                                         if ( $2 != "n/a" ) {
4589                                                 prettyName = $2
4590                                         }
4591                                 }
4592                                 /^NAME/ {
4593                                         if ( $2 != "n/a" ) {
4594                                                 regularName = $2
4595                                         }
4596                                 }
4597                                 /^VERSION/ {
4598                                         if ( $2 != "n/a" && $1 == "VERSION" ) {
4599                                                 versionName = $2
4600                                         }
4601                                         else if ( $2 != "n/a" && $1 == "VERSION_ID" ) {
4602                                                 versionId = $2
4603                                         }
4604                                 }
4605                                 END {
4606                                         if ( prettyName != "" ) {
4607                                                 distroName = prettyName
4608                                         }
4609                                         else if ( regularName != "" ) {
4610                                                 distroName = regularName
4611                                                 if ( versionName != "" ) {
4612                                                         distroName = distroName " " versionName
4613                                                 }
4614                                                 else if ( versionId != "" ) {
4615                                                         distroName = distroName " " versionId
4616                                                 }
4617                                                 
4618                                         }
4619                                         print distroName
4620                                 }
4621                                 ' $FILE_OS_RELEASE )
4622                                 log_function_data 'cat' "$FILE_OS_RELEASE"
4623                         fi
4624                         ;;
4625         esac
4626         echo $distro
4627         log_function_data "distro: $distro"
4628         eval $LOGFE
4629 }
4630
4631 get_dmidecode_data()
4632 {
4633         eval $LOGFS
4634         
4635         local dmidecodePath=''
4636
4637         if [[ $B_DMIDECODE_SET != 'true' ]];then
4638                 dmidecodePath=$( type -p dmidecode 2>/dev/null )
4639                 if [[ -n $dmidecodePath ]];then
4640                         # note stripping out these lines: Handle 0x0016, DMI type 17, 27 bytes
4641                         # but NOT deleting them, in case the dmidecode data is missing empty lines which will be
4642                         # used to separate results. Then we remove the doubled empty lines to keep it clean and
4643                         # strip out all the stuff we don't want to see in the results.
4644                         DMIDECODE_DATA="$( $dmidecodePath 2>/dev/null \
4645                         | gawk -F ':' '
4646                         BEGIN {
4647                                 IGNORECASE=1
4648                                 cutExtraTab="false"
4649                                 twoData=""
4650                                 oneData=""
4651                         }
4652                         {
4653                                 # no idea why, but freebsd gawk does not do this right
4654                                 oneData=$1
4655                                 twoData=$2
4656                                 if ( twoData != "" ) {
4657                                         twoHolder="true"
4658                                 }
4659                                 else {
4660                                         twoHolder="false"
4661                                 }
4662                                 if ( $0 ~ /^\tDMI type/ ) {
4663                                         sub(/^\tDMI type.*/, "", $0)
4664                                         cutExtraTab="true"
4665                                 }
4666                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", twoData)
4667                                 gsub(/,/, " ", $0)
4668                                 # clean out Handle line
4669                                 sub(/^Handle.*/,"", $0)
4670                                 sub(/^[[:space:]]*Inactive.*/,"",$0)
4671                                 # yes, there is a typo in a user data set, unknow
4672                                 # Base Board Version|Base Board Serial Number
4673                                 # Chassis Manufacturer|Chassis Version|Chassis Serial Number
4674                                 # System manufacturer|System Product Name|System Version
4675                                 # To Be Filled By O.E.M.
4676                                 # strip out starting white space so that the following stuff will clear properly
4677                                 sub(/^[[:space:]]+/, "", twoData)
4678                                 sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", twoData) 
4679                                 gsub(/bios|acpi/, "", twoData)
4680                                 sub(/http:\/\/www.abit.com.tw\//, "Abit", twoData)
4681                                 
4682                                 # for double indented values replace with ~ so later can test for it, we are trusting that
4683                                 # indentation will be tabbed in this case
4684                                 # special case, dmidecode 2.2 has an extra tab and a DMI type line
4685                                 if ( cutExtraTab == "true" ) {
4686                                         sub(/^\t\t\t+/, "~", oneData)
4687                                 }
4688                                 else {
4689                                         sub(/^\t\t+/, "~", oneData)
4690                                 }
4691                                 
4692                                 gsub(/^[[:space:]]+|[[:space:]]+$/, "", twoData)
4693                                 gsub(/^[[:space:]]+|[[:space:]]+$/, "", oneData)
4694                                 gsub(/ [ \t]+/, " ", twoData)
4695                                 # reconstructing the line for processing so gawk can use -F : again
4696                                 if ( oneData != "" && twoHolder == "true" ) {
4697                                         print oneData ":" twoData
4698                                 }
4699                                 else {
4700                                         print $0
4701                                 }
4702                         }' \
4703                         | sed '/^$/{
4704 N
4705 /^\n$/D
4706 }' \
4707                         )"
4708                 fi
4709                 B_DMIDECODE_SET='true'
4710                 log_function_data "DMIDECODE_DATA: $DMIDECODE_DATA"
4711         fi
4712
4713         eval $LOGFE
4714 }
4715 # get_dmidecode_data;echo "$DMIDECODE_DATA";exit
4716
4717 # BSD only
4718 get_dmesg_boot_data()
4719 {
4720         eval $LOGFS
4721         
4722         local dmsg_boot_data=''
4723         
4724         if [[ $B_DMESG_BOOT_FILE == 'true' ]];then
4725                 # replace all indented items with ~ so we can id them easily while processing
4726                 dmsg_boot_data="$( cat $FILE_DMESG_BOOT | sed $SED_RX 's/"//g' )"
4727         fi
4728         echo "$dmsg_boot_data"
4729         # log_function_data "$dmsg_boot_data"
4730         eval $LOGFE
4731 }
4732
4733 get_gcc_kernel_version()
4734 {
4735         # note that we use gawk to get the last part because beta, alpha, git versions can be non-numeric
4736         local gccVersion=''
4737         
4738         if [[ -e /proc/version ]];then
4739                 gccVersion=$( grep -Eio 'gcc[[:space:]]*version[[:space:]]*([^ \t]*)' /proc/version 2>/dev/null | gawk '{print $3}' )
4740         fi
4741         echo $gccVersion
4742 }
4743
4744 get_gcc_system_version()
4745 {
4746         eval $LOGFS
4747         local separator='' gcc_installed='' gcc_list='' gcc_others='' temp_array=''
4748         local gcc_version=$( 
4749         gcc --version 2>/dev/null | sed $SED_RX 's/\([^\)]*\)//g' | gawk '
4750         BEGIN {
4751                 IGNORECASE=1
4752         }
4753         /^gcc/ {
4754                 print $2
4755                 exit
4756         }'      )
4757
4758         # can't use xargs -L basename because not all systems support thats
4759         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
4760                 gcc_others=$( ls /usr/bin/gcc-* 2>/dev/null )
4761                 if [[ -n $gcc_others ]];then
4762                         for item in $gcc_others
4763                         do
4764                                 gcc_installed=$( basename $item | gawk -F '-' '
4765                                 $2 ~ /^[0-9\.]+$/ {
4766                                         print $2
4767                                 }' )
4768                                 if [[ -n $gcc_installed && -z $( grep "^$gcc_installed" <<< $gcc_version ) ]];then
4769                                         gcc_list=$gcc_list$separator$gcc_installed
4770                                         separator=','
4771                                 fi
4772                         done
4773                 fi
4774         fi
4775         if [[ -n $gcc_version ]];then
4776                 A_GCC_VERSIONS=( "$gcc_version" $gcc_list )
4777         fi
4778         temp_array=${A_GCC_VERSIONS[@]}
4779         log_function_data "A_GCC_VERSIONS: $temp_array"
4780         eval $LOGFE
4781 }
4782 get_gpu_temp_data()
4783 {
4784         local gpu_temp='' gpu_fan='' screens='' screen_nu='' gpu_temp_looper=''
4785
4786         # we'll try for nvidia/ati, then add if more are shown
4787         if [[ -n $( type -p nvidia-settings ) ]];then
4788                 # first get the number of screens
4789                 screens=$( nvidia-settings -q screens | gawk '
4790                 /:[0-9]\.[0-9]/ {
4791                         screens=screens gensub(/(.*)(:[0-9]\.[0-9])(.*)/, "\\2", "1", $0) " "
4792                 }
4793                 END {
4794                         print screens
4795                 }
4796                 ' )
4797                 # now we'll get the gpu temp for each screen discovered. The print out function
4798                 # will handle removing screen data for single gpu systems
4799                 for screen_nu in $screens
4800                 do
4801                         gpu_temp_looper=$( nvidia-settings -c $screen_nu -q GPUCoreTemp | gawk -F ': ' '
4802                         BEGIN {
4803                                 IGNORECASE=1
4804                                 gpuTemp=""
4805                                 gpuTempWorking=""
4806                         }
4807                         /Attribute (.*)[0-9]+\.$/ {
4808                                 gsub(/\./, "", $2)
4809                                 if ( $2 ~ /^[0-9]+$/ ) {
4810                                         gpuTemp=gpuTemp $2 "C "
4811                                 }
4812                         }
4813                         END {
4814                                 print gpuTemp
4815                         }'      )
4816                         screen_nu=$( cut -d ':' -f 2 <<< $screen_nu )
4817                         gpu_temp="$gpu_temp$screen_nu:$gpu_temp_looper "
4818                 done
4819         elif [[ -n $( type -p aticonfig ) ]];then
4820 #               gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' '
4821                 gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' '
4822                 BEGIN {
4823                         IGNORECASE=1
4824                         gpuTemp=""
4825                         gpuTempWorking=""
4826                 }
4827                 /Sensor (.*)[0-9\.]+ / {
4828                         gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2)
4829                         if ( gpuTempWorking ~ /^[0-9\.]+$/ ) {
4830                                 gpuTemp=gpuTemp gpuTempWorking "C "
4831                         }
4832                 }
4833                 END {
4834                         print gpuTemp
4835                 }'      )
4836         # this handles some newer cases of free driver temp readouts, will require modifications as
4837         # more user data appears.
4838         elif [[ -n $Sensors_Data ]];then
4839                 gpu_temp=$( 
4840                 gawk '
4841                 BEGIN {
4842                         IGNORECASE=1
4843                         gpuTemp=""
4844                         separator=""
4845                 }
4846                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
4847                         while ( getline && !/^$/  ) {
4848                                 if ( /^temp/ ) {
4849                                         sub(/^[[:alnum:]]*.*:/, "", $0 ) # clear out everything to the :
4850                                         gsub(/[\+ \t°]/, "", $1) # Â° is a special case, like a space for gawk
4851                                         gpuTemp=gpuTemp separator $1
4852                                         separator=","
4853                                 }       
4854                         }
4855                 }
4856                 END {
4857                         print gpuTemp
4858                 }' <<< "$Sensors_Data" )
4859         fi
4860         
4861         if [[ -n $gpu_temp ]];then
4862                 echo $gpu_temp
4863         fi
4864 }
4865
4866 ## for possible future data, not currently used
4867 get_graphics_agp_data()
4868 {
4869         eval $LOGFS
4870         local agp_module=''
4871
4872         if [[ $B_MODULES_FILE == 'true' ]];then
4873                 ## not used currently
4874                 agp_module=$( gawk '
4875                 /agp/ && !/agpgart/ && $3 > 0 {
4876                         print(gensub(/(.*)_agp.*/,"\\1","g",$1))
4877                 }' $FILE_MODULES )
4878                 log_function_data 'cat' "$FILE_MODULES"
4879         fi
4880         log_function_data "agp_module: $agp_module"
4881         eval $LOGFE
4882 }
4883
4884 ## create array of gfx cards installed on system
4885 get_graphics_card_data()
4886 {
4887         eval $LOGFS
4888         local i='' temp_array=''
4889
4890         IFS=$'\n'
4891         A_GRAPHICS_CARD_DATA=( $( gawk -F': ' '
4892         BEGIN {
4893                 IGNORECASE=1
4894                 busId=""
4895         }
4896         /vga compatible controller/ {
4897                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF)
4898                 gsub(/,/, " ", $NF)
4899                 gsub(/^ +| +$/, "", $NF)
4900                 gsub(/ [ \t]+/, " ", $NF)
4901                 busId=gensub(/^([0-9a-f:\.]+) (.+)$/,"\\1","",$1)
4902                 print $NF "," busId
4903         }' <<< "$Lspci_v_Data" ) )
4904         IFS="$ORIGINAL_IFS"
4905 #       for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
4906 #       do
4907 #               A_GRAPHICS_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GRAPHICS_CARD_DATA[i]}" )
4908 #       done
4909
4910         # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory..
4911         # 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]"
4912         temp_array=${A_GRAPHICS_CARD_DATA[@]}
4913         log_function_data "A_GRAPHICS_CARD_DATA: $temp_array"
4914         eval $LOGFE
4915 }
4916
4917 get_graphics_driver()
4918 {
4919         eval $LOGFS
4920         
4921         # list is from sgfxi plus non-free drivers
4922         local driver_list='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'
4923         local driver='' driver_string='' xorg_log_data='' status='' temp_array=''
4924
4925         if [[ $B_XORG_LOG == 'true' ]];then
4926                 A_GRAPHIC_DRIVERS=( $(
4927                 gawk '
4928                 BEGIN {
4929                         driver=""
4930                         bLoaded="false"
4931                         IGNORECASE=1
4932                 }
4933                 # note that in file names, driver is always lower case
4934                 /[[:space:]]Loading.*('"$driver_list"')_drv.so$/ {
4935                         driver=gensub(/.*[[:space:]]Loading.*('"$driver_list"')_drv.so/, "\\1", 1, $0 )
4936                         # we get all the actually loaded drivers first, we will use this to compare the
4937                         # failed/unloaded, which have not always actually been truly loaded
4938                         aDrivers[driver]="loaded" 
4939                 }
4940                 /Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/ {
4941                         driver=gensub(/(.*)Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/, "\\2", 1, $0 )
4942                         # we need to make sure that the driver has already been truly loaded, not just discussed
4943                         if ( driver in aDrivers ) {
4944                                 aDrivers[driver]="unloaded"
4945                         }
4946                 }
4947                 /Failed.*('"$driver_list"')_drv.so|Failed.*\"('"$driver_list"')\"/ {
4948                         driver=gensub(/(.*)Failed.*('"$driver_list"')_drv.so/, "\\2", 1, $0 )
4949                         if ( driver == $0 ) {
4950                                 driver=gensub(/(.*)Failed.*\"('"$driver_list"')\".*|fred/, "\\2", 1, $0 )
4951                         }
4952                         # we need to make sure that the driver has already been truly loaded, not just discussed
4953                         if ( driver != $0 && driver in aDrivers ) {
4954                                 aDrivers[driver]="failed"
4955                         }
4956                 }
4957                 # verify that the driver actually started the desktop, even with false failed messages which can occur
4958                 # this is the driver that is actually driving the display
4959                 /.*\([0-9]+\):[[:space:]]Depth.*framebuffer/ {
4960                         driver=gensub(/.*('"$driver_list"')\([0-9]+\):[[:space:]]Depth.*framebuffer.*/, "\\1", 1, $0 )
4961                         # we need to make sure that the driver has already been truly loaded, not just discussed, also
4962                         # set driver to lower case because sometimes it will show as RADEON or NVIDIA in the actual x start
4963                         driver=tolower(driver)
4964                         if ( driver != $0 && driver in aDrivers ) {
4965                                 aDrivers[driver]="loaded"
4966                         }
4967                 }
4968                 END {
4969                         for ( driver in aDrivers ) {
4970                                 print driver "," aDrivers[driver]
4971                         }
4972                 }' < $FILE_XORG_LOG ) )
4973         fi
4974         temp_array=${A_GRAPHIC_DRIVERS[@]}
4975         log_function_data "A_GRAPHIC_DRIVERS: $temp_array"
4976         
4977         eval $LOGFE
4978 }
4979
4980 ## create array of glx data
4981 get_graphics_glx_data()
4982 {
4983         eval $LOGFS
4984         local temp_array=''
4985         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
4986                 IFS=$'\n'
4987                 A_GLX_DATA=( $( glxinfo | gawk -F ': ' '
4988                 # note: function declarations go before BEGIN? It appears so, confirm.
4989                 # the real question here though is why this function is even here, seems
4990                 # just to be a complicated way to pack/print a variable, but maybe the
4991                 # original idea was to handle > 1 cases of detections I guess
4992                 function join( arr, sep ) {
4993                         s=""
4994                         i=flag=0
4995                         for ( i in arr ) {
4996                                 if ( flag++ ) {
4997                                         s = s sep
4998                                 }
4999                                 s = s i
5000                         }
5001                         return s
5002                 }
5003
5004                 BEGIN {
5005                         IGNORECASE=1
5006                 }
5007                 /opengl renderer/ {
5008                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
5009                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
5010                         gsub(/^ +| +$/, "", $2)
5011                         if ( $2 ~ /mesa/ ) {
5012                                 # Allow all mesas
5013 #                               if ( $2 ~ / r[3-9][0-9][0-9] / ) {
5014                                         a[$2]
5015                                         # this counter failed in one case, a bug, and is not needed now
5016 #                                       f++
5017 #                               }
5018                                 next
5019                         }
5020                         
5021                         $2 && a[$2]
5022                 }
5023                 # dropping all conditions from this test to just show full mesa information
5024                 # there is a user case where not f and mesa apply, atom mobo
5025                 # /opengl version/ && ( f || $2 !~ /mesa/ ) {
5026                 /opengl version/ {
5027                         # fglrx started appearing with this extra string, does not appear to communicate anything of value
5028                         sub(/Compatibility Profile Context/, "- CPC", $2 )
5029                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
5030                         gsub(/^ +| +$/, "", $2)
5031                         $2 && b[$2]
5032                 }
5033                 /direct rendering/ {
5034                         $2 && c[$2]
5035                 }
5036                 END {
5037                         printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) )
5038                 }' ) )
5039                 IFS="$ORIGINAL_IFS"
5040
5041                 # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
5042                 #    GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
5043         fi
5044         temp_array=${A_GLX_DATA[@]}
5045         log_function_data "A_GLX_DATA: $temp_array"
5046         eval $LOGFE
5047 }
5048
5049 ## return screen resolution / tty resolution
5050 get_graphics_res_data()
5051 {
5052         eval $LOGFS
5053         local screen_resolution='' xdpy_data='' screens_count=0 tty_session=''
5054
5055         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
5056                 # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in
5057                 # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0
5058                 xdpy_data="$( xdpyinfo )"
5059                 xdpy_count=$( grep -c 'dimensions' <<< "$xdpy_data" )
5060                 # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
5061                 # multiple screens from different video cards
5062                 if [[ $xdpy_count -eq 1 ]];then
5063                         screen_resolution=$( xrandr | gawk '
5064                         /\*/ {
5065                                 res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0)
5066                         }
5067                         END {
5068                                 for (n in res) {
5069                                         if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) {
5070                                                 line = line ? line ", " res[n] : res[n]
5071                                         }
5072                                 }
5073                                 if (line) {
5074                                         print(line)
5075                                 }
5076                         }' )
5077                 fi
5078                 if [[ -z $screen_resolution || $xdpy_count -gt 1 ]];then
5079                         screen_resolution=$( gawk '
5080                         BEGIN {
5081                                 IGNORECASE=1
5082                                 screens = ""
5083                                 separator = ""
5084                         }
5085                         /dimensions/ {
5086                                 screens = screens separator # first time, this is null, next, has comma last
5087                                 screens = screens $2 # then tack on the new value for nice comma list
5088                                 separator = ", "
5089                         }
5090                         END {
5091                                 print screens
5092                         }' <<< "$xdpy_data" )
5093                 fi
5094         else
5095                 if [[ $B_PROC_DIR == 'true' && -z $BSD_TYPE ]];then
5096                         screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{
5097                                 print $2"x"$1
5098                         }' )
5099                 # note: this works fine for all systems but keeping the above for now since
5100                 # the above is probably more accurate for linux systems.
5101                 else
5102                         if [[ $B_CONSOLE_IRC != 'true' ]];then
5103                                 screen_resolution=$( stty -a | gawk -F ';' '
5104                                         /^speed/ {
5105                                                 gsub(/[[:space:]]*(rows|columns)[[:space:]]*/,"",$0)
5106                                                 gsub(/[[:space:]]*/,"",$2)
5107                                                 gsub(/[[:space:]]*/,"",$3)
5108                                                 print $3"x"$2
5109                                         }' )
5110                         else
5111                                 if [[ -n $BSD_TYPE ]];then
5112                                         tty_session=$( get_tty_console_irc )
5113                                         # getting information for tty that owns the irc client
5114                                         screen_resolution="$( stty -f /dev/pts/$tty_session size | gawk '{print $2"x"$1}' )"
5115                                 fi
5116                         fi
5117                 fi
5118         fi
5119         echo "$screen_resolution"
5120         log_function_data "screen_resolution: $screen_resolution"
5121         eval $LOGFE
5122 }
5123
5124 ## create array of display server vendor/version data
5125 get_graphics_display_server_data()
5126 {
5127         eval $LOGFS
5128         local vendor='' version='' temp_array='' xdpy_info='' a_display_vendor_working=''
5129
5130         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
5131                 # X vendor and version detection.
5132                 # new method added since radeon and X.org and the disappearance of <X server name> version : ...etc
5133                 # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2
5134                 # A failover mechanism is in place. (if $version is empty, the release number is parsed instead)
5135                 # xdpy_info="$( xdpyinfo )"
5136                 IFS=","
5137                 a_display_vendor_working=( $( xdpyinfo | gawk -F': +' '
5138                 BEGIN {
5139                         IGNORECASE=1
5140                         vendorString=""
5141                         version=""
5142                         vendorRelease=""
5143                 }
5144                 /vendor string/ {
5145                         gsub(/the|inc|foundation|project|corporation/, "", $2)
5146                         gsub(/,/, " ", $2)
5147                         gsub(/^ +| +$/, "", $2)
5148                         gsub(/ [ \t]+/, " ", $2)
5149                         vendorString = $2
5150                 }
5151                 /version:/ {
5152                         version = $NF
5153                 }
5154                 /vendor release number/ {
5155                         gsub(/0+$/, "", $2)
5156                         gsub(/0+/, ".", $2)
5157                         vendorRelease = $2
5158                 }
5159                 END {
5160                         print vendorString "," version "," vendorRelease
5161                 }' ) )
5162                 vendor=${a_display_vendor_working[0]}
5163                 version=${a_display_vendor_working[1]}
5164
5165                 # this gives better output than the failure last case, which would only show:
5166                 # for example: X.org: 1.9 instead of: X.org: 1.9.0
5167                 if [[ -z $version ]];then
5168                         version=$( get_graphics_display_server_version )
5169                 fi
5170                 if [[ -z $version ]];then
5171                         version=${a_display_vendor_working[2]}
5172                 fi
5173                 
5174                 # some distros, like fedora, report themselves as the xorg vendor, so quick check
5175                 # here to make sure the vendor string includes Xorg in string
5176                 if [[ -z $( grep -E '(X|xorg|x\.org)' <<< $vendor ) ]];then
5177                         vendor="$vendor X.org"
5178                 fi
5179                 IFS="$ORIGINAL_IFS"
5180                 A_DISPLAY_SERVER_DATA[0]="$vendor"
5181                 A_DISPLAY_SERVER_DATA[1]="$version"
5182         else
5183                 version=$( get_graphics_display_server_version )
5184                 if [[ -n $version ]];then
5185                         vendor='X.org'
5186                         A_DISPLAY_SERVER_DATA[0]="$vendor"
5187                         A_DISPLAY_SERVER_DATA[1]="$version"
5188                 fi
5189         fi
5190         temp_array=${A_DISPLAY_SERVER_DATA[@]}
5191         log_function_data "A_DISPLAY_SERVER_DATA: $temp_array"
5192         eval $LOGFE
5193 }
5194
5195 # if other tests fail, try this one, this works for root, out of X also
5196 get_graphics_display_server_version()
5197 {
5198         eval $LOGFS
5199         local version='' x_data=''
5200         # note that some users can have /usr/bin/Xorg but not /usr/bin/X
5201         if [[ -n $( type -p X ) ]];then
5202                 # note: MUST be this syntax: X -version 2>&1
5203                 # otherwise X -version overrides everything and this comes out null.
5204                 # two knowns id strings: X.Org X Server 1.7.5 AND X Window System Version 1.7.5
5205                 #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }'
5206                 x_data="$( X -version 2>&1 )"
5207         elif [[ -n $( type -p Xorg ) ]];then
5208                 x_data="$( Xorg -version 2>&1)"
5209         fi
5210         if [[ -n $x_data ]];then
5211                 version=$( 
5212                 gawk '
5213                 BEGIN {
5214                         IGNORECASE=1
5215                 }
5216                 /^x.org x server/ {
5217                         print $4
5218                         exit
5219                 }
5220                 /^X Window System Version/ {
5221                         print $5
5222                         exit
5223                 }' <<< "$x_data" )
5224         fi
5225         echo $version
5226         log_function_data " version: $version"
5227         eval $LOGFE
5228 }
5229
5230 # this gets just the raw data, total space/percent used and disk/name/per disk capacity
5231 get_hdd_data_basic()
5232 {
5233         eval $LOGFS
5234         local hdd_used='' temp_array='' df_string=''
5235         local hdd_data='' df_test=''
5236         
5237         if [[ -z $BSD_TYPE ]];then
5238                 df_string='df -P -T --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
5239                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs
5240                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs'
5241         else
5242                 # default size is 512, so use -k for 1024
5243                 df_string='df -T -k'
5244                 # default size is 512, -H only for size in human readable format
5245                 # older bsds don't support -T, pain, so we'll use partial output there
5246                 df_test=$( df -H -T 2>/dev/null )
5247                 if [[ -n $df_test ]];then
5248                         df_string='df -k -T'
5249                 else
5250                         df_string='df -k'
5251                 fi
5252         fi
5253         hdd_data="$( eval $df_string )"
5254         log_function_data 'raw' "hdd_data:\n$hdd_data"
5255         hdd_used=$(     echo "$hdd_data" | gawk -v bsdType=$BSD_TYPE '
5256         BEGIN {
5257                 # this is used for specific cases where bind, or incorrect multiple mounts to same partitions,
5258                 # is present. The value is searched for an earlier appearance of that partition and if it is 
5259                 # present, the data is not added into the partition used size.
5260                 partitionsSet=""
5261                 # this handles a case where the same dev item is mounted twice to different points
5262                 devSet=""
5263                 devWorking=""
5264                 mountWorking=""
5265         }
5266         # using $1, not $2, because older bsd df do not have -T, filesystem type
5267         ( bsdType != "" ) && $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|filesystem|iso9660|linprocfs|procfs|squashfs|sysfs|tmpfs|type|unionfs)$/ {
5268                 # note use next, not getline or it does not work right
5269                 next 
5270         }
5271         # also handles odd dm-1 type, from lvm, and mdraid, and some other bsd partition syntax
5272         # note that linux 3.2.45-grsec-9th types kernels have this type of partition name: /dev/xvdc (no number, letter)
5273         /^\/dev\/(mapper\/|[hsv]d[a-z][0-9]+|dm[-]?[0-9]+|ada[0-9]+p[0-9]+.*|md[0-9]+|[aw]d[0-9]+s.*|xvd[a-z])/ {
5274                 # this handles the case where the first item is too long
5275                 # and makes df wrap output to next line, so here we advance
5276                 # it to the next line for that single case. Using df -P should
5277                 # make this unneeded but leave it in just in case
5278                 if ( NF < 6 && $0 !~ /.*%/ ) {
5279                         devSet = devSet "~" $1 "~"
5280                         getline
5281                 }
5282                 # if the first item caused a wrap, use one less than standard
5283                 # testing for the field with % in it, ie: 34%, then go down from there
5284                 # this also protects against cases where the mount point has a space in the
5285                 # file name, thus breaking going down from $NF directly.
5286                 # some bsds will also have only 6 items
5287                 if ( $5 ~ /.*%/ ) {
5288                         devWorking="~" $1 "~"
5289                         mountWorking="~" $6 "~"
5290                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
5291                                 used += $3
5292                         }
5293                         partitionsSet = partitionsSet mountWorking
5294                         # make sure to only include bsd real lines here, ie, short df output
5295                         if ( $1 ~ /^\/dev\// ) {
5296                                 devSet = devSet devWorking
5297                         }
5298                 }
5299                 # otherwise use standard
5300                 else if ( $6 ~ /.*%/ ) {
5301                         devWorking="~" $1 "~"
5302                         mountWorking="~" $7 "~"
5303                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
5304                                 used += $4
5305                         }
5306                         partitionsSet = partitionsSet mountWorking
5307                         devSet = devSet devWorking
5308                 }
5309                 # and if this is not detected, give up, we need user data to debug
5310                 else {
5311                         next
5312                 }
5313         }
5314         END {
5315                 print used
5316         }' )
5317
5318         if [[ -z $hdd_used ]];then
5319                 hdd_used='na'
5320         fi
5321         log_function_data "hdd_used: $hdd_used"
5322         # create the initial array strings:
5323         # disk-dev, capacity, name, usb or not
5324         # final item is the total of the disk
5325         IFS=$'\n'
5326
5327         if [[ $B_PARTITIONS_FILE == 'true' ]];then
5328                 A_HDD_DATA=( $(
5329                 gawk -v hddused="$hdd_used" '
5330                 /[hsv]d[a-z]$/ {
5331                         driveSize = $(NF - 1)*1024/1000**3
5332                         gsub(/,/, " ", driveSize)
5333                         gsub(/^ +| +$/, "", driveSize)
5334                         printf( $NF",%.1fGB,,\n", driveSize )
5335                 }
5336                 # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
5337                 # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0  {
5338                 #       size += $3
5339                 # }
5340                 # special case from this data: 8     0  156290904 sda
5341                 # note: vm has 252/253/254 known starter, grsec has 202
5342                 $1 ~ /^(3|8|22|33|202|252|253|254)$/ && $NF ~ /[hsv]d[a-z]$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) {
5343                         size += $3
5344                 }
5345
5346                 END {
5347                         size = size*1024/1000**3                   # calculate size in GB size
5348                         workingUsed = hddused*1024/1000**3         # calculate workingUsed in GB used
5349                         # this handles a special case with livecds where no hdd_used is detected
5350                         if ( size > 0 && hddused == "na" ) {
5351                                 size = sprintf( "%.1f", size )
5352                                 print size "GB,-"
5353                         }
5354                         else if ( size > 0 && workingUsed > 0 ) {
5355                                 diskUsed = workingUsed*100/size  # calculate used percentage
5356                                 diskUsed = sprintf( "%.1f", diskUsed )
5357                                 size = sprintf( "%.1f", size )
5358                                 print size "GB," diskUsed "% used"
5359                         }
5360                         else {
5361                                 print "NA,-" # print an empty array, this will be further handled in the print out function
5362                         }
5363                 }' $FILE_PARTITIONS ) )
5364                 log_function_data 'cat' "$FILE_PARTITIONS"
5365         fi
5366         IFS="$ORIGINAL_IFS"
5367         temp_array=${A_HDD_DATA[@]}
5368         log_function_data "A_HDD_DATA: $temp_array"
5369         eval $LOGFE
5370 }
5371
5372 ## fills out the A_HDD_DATA array with disk names
5373 get_hard_drive_data_advanced()
5374 {
5375         eval $LOGFS
5376         local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j=''
5377         local sd_ls_by_id='' ls_disk_by_id='' usb_exists='' temp_array=''
5378
5379         ## check for all ide type drives, non libata, only do it if hdx is in array
5380         ## this is now being updated for new /sys type paths, this may handle that ok too
5381         if [[ -n $( grep -E 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
5382                 # remember, we're using the last array item to store the total size of disks
5383                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
5384                 do
5385                         IFS=","
5386                         a_temp_working=( ${A_HDD_DATA[i]} )
5387                         IFS="$ORIGINAL_IFS"
5388                         if [[ -n $( grep -E '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];then
5389                                 if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then
5390                                         a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )"
5391                                 else
5392                                         a_temp_working[2]="Name n/a"
5393                                 fi
5394                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
5395                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
5396                                 do
5397                                         if [[ $j -gt 0 ]];then
5398                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
5399                                         else
5400                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
5401                                         fi
5402                                 done
5403                         fi
5404                 done
5405         fi
5406
5407         ## then handle libata names
5408         # first get the ata device names, put them into an array
5409         IFS=$'\n'
5410         if [[ $B_SCSI_FILE == 'true' ]]; then
5411                 a_temp_scsi=( $( gawk  '
5412                 BEGIN {
5413                         IGNORECASE=1
5414                 }
5415                 /host/ {
5416                         getline a[$0]
5417                         getline b[$0]
5418                 }
5419                 END {
5420                         for (i in a) {
5421                                 if (b[i] ~ / *type: *direct-access.*/) {
5422                                         #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i])
5423                                         #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] )
5424                                         # the vendor: string is useless, and is a bug, ATA is not a vendor for example
5425                                         c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] )
5426                                         gsub(/,/, " ", c)
5427                                         gsub(/^ +| +$/, "", c)
5428                                         gsub(/ [ \t]+/, " ", c)
5429                                         #print a[i]
5430                                         # we actually want this data, so leaving this off for now
5431 #                                       if (c ~ /\<flash\>|\<pendrive\>|memory stick|memory card/) {
5432 #                                               continue
5433 #                                       }
5434                                         print c
5435                                 }
5436                         }
5437                 }' $FILE_SCSI ) )
5438                 log_function_data 'cat' "$FILE_SCSI"
5439         fi
5440         IFS="$ORIGINAL_IFS"
5441
5442         ## then we'll loop through that array looking for matches.
5443         if [[ -n $( grep -E 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
5444                 # first pack the main ls variable so we don't have to keep using ls /dev...
5445                 # not all systems have /dev/disk/by-id
5446                 ls_disk_by_id="$( ls -l /dev/disk/by-id 2>/dev/null )"
5447                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
5448                 do
5449                         if [[ -n $( grep -E '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then
5450                                 IFS=","
5451                                 a_temp_working=( ${A_HDD_DATA[$i]} )
5452                                 IFS="$ORIGINAL_IFS"
5453                                 # /sys/block/[sda,hda]/device/model
5454                                 # this is handles the new /sys data types first
5455                                 if [[ -e /sys/block/${a_temp_working[0]}/device/model ]];then
5456                                         temp_name="$( remove_erroneous_chars /sys/block/${a_temp_working[0]}/device/model )"
5457                                         temp_name=$( tr ' ' '_' <<< $temp_name | cut -d '-' -f 1 )
5458                                 elif [[ ${#a_temp_scsi[@]} -gt 0 ]];then
5459                                         for (( j=0; j < ${#a_temp_scsi[@]}; j++ ))
5460                                         do
5461                                                 ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
5462                                                 # discovered disk name AND ends with the correct identifier, sdx
5463                                                 # get rid of whitespace for some drive names and ids, and extra data after - in name
5464                                                 temp_name=$( tr ' ' '_' <<< ${a_temp_scsi[$j]} | cut -d '-' -f 1 )
5465                                                 sd_ls_by_id=$( grep -Em1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
5466
5467                                                 if [[ -n $sd_ls_by_id ]];then
5468                                                         temp_name=${a_temp_scsi[$j]}
5469                                                         break
5470                                                 else
5471                                                         # test to see if we can get a better name output when null
5472                                                         if [[ -n $temp_name ]];then
5473                                                                 temp_name=$temp_name
5474                                                         fi
5475                                                 fi
5476                                         done
5477                                 fi
5478                                 
5479                                 if [[ -z $temp_name ]];then
5480                                         temp_name="Name n/a"
5481                                 else 
5482                                         usb_exists=$( grep -Em1 "usb-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
5483                                         if [[ -n $usb_exists ]];then
5484                                                 a_temp_working[3]='USB'
5485                                         fi
5486                                 fi
5487                                 a_temp_working[2]=$temp_name
5488                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
5489                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
5490                                 do
5491                                         if [[ $j -gt 0 ]];then
5492                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
5493                                         else
5494                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
5495                                         fi
5496                                 done
5497                         fi
5498                 done
5499                 unset ls_disk_by_id # and then let's dump the data we don't need
5500         fi
5501         temp_array=${A_HDD_DATA[@]}
5502         log_function_data "A_HDD_DATA: $temp_array"
5503         eval $LOGFE
5504 }
5505
5506 # args: $1 - which drive to get serial number of
5507 get_hdd_serial_number()
5508 {
5509         eval $LOGFS
5510         
5511         local hdd_serial=''
5512         
5513         get_partition_dev_data 'id'
5514         
5515         # lrwxrwxrwx 1 root root  9 Apr 26 09:32 scsi-SATA_ST3160827AS_5MT2HMH6 -> ../../sdc
5516         # exit on the first instance
5517         hdd_serial=$( gawk '
5518         /'$1'$/ {
5519                 serial=gensub( /^(.+)_([^_]+)$/, "\\2", 1, $9 )
5520                 print serial
5521                 exit
5522         }' <<< "$DEV_DISK_ID" )
5523         
5524         echo $hdd_serial
5525         log_function_data "hdd serial: $hdd_serial"
5526         eval $LOGFE
5527 }
5528
5529 # a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers.
5530 # args: $1 - /dev/<disk> to be tested for
5531 get_hdd_temp_data()
5532 {
5533         eval $LOGFS
5534         local hdd_temp='' sudo_command='' 
5535
5536         if [[ $B_HDDTEMP_TESTED != 'true' ]];then
5537                 B_HDDTEMP_TESTED='true'
5538                 HDDTEMP_PATH=$( type -p hddtemp )
5539         fi
5540         if [[ $B_SUDO_TESTED != 'true' ]];then
5541                 B_SUDO_TESTED='true'
5542                 SUDO_PATH=$( type -p sudo )
5543         fi
5544         
5545         if [[ -n $HDDTEMP_PATH && -n $1 ]];then
5546                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
5547                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
5548                 # important: -n makes it non interactive, no prompt for password
5549                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
5550                         sudo_command='sudo -n '
5551                 fi
5552                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
5553                 hdd_temp=$( eval $sudo_command $HDDTEMP_PATH -nq -u C $1 )
5554                 if [[ -n $hdd_temp && -n $( grep -E '^([0-9\.]+)$' <<< $hdd_temp ) ]];then
5555                         echo $hdd_temp
5556                 fi
5557         fi
5558         eval $LOGFE
5559 }
5560
5561 get_init_data()
5562 {
5563         eval $LOGFS
5564         
5565         local init_type='' init_version='' rc_type='' rc_version='' temp_array=''
5566         local ls_run='' strings_init_version=''
5567         local runlevel=$( get_runlevel_data )
5568         local default_runlevel=$( get_runlevel_default )
5569         
5570         # this test is pretty solid, if pid 1 is owned by systemd, it is systemd
5571         # otherwise that is 'init', which covers the rest of the init systems, I think anyway.
5572         # more data may be needed for other init systems.
5573         if [[ -e /proc/1/comm && -n $( grep -s 'systemd' /proc/1/comm ) ]];then
5574                 init_type='systemd'
5575                 if [[ -n $( type -p systemd ) ]];then
5576                         init_version=$( get_de_app_version 'systemd' '^systemd' '2' )
5577                 fi
5578                 if [[ -z $init_version && -n $( type -p systemctl ) ]];then
5579                         init_version=$( get_de_app_version 'systemctl' '^systemd' '2' )
5580                 fi
5581         else
5582                 ls_run=$(ls /run)
5583                 # note: upstart-file-bridge.pid upstart-socket-bridge.pid upstart-udev-bridge.pid
5584                 if [[ -n $( /sbin/init --version 2>/dev/null | grep 'upstart' ) ]];then
5585                         init_type='Upstart'
5586                         # /sbin/init --version == init (upstart 1.12.1)
5587                         init_version=$( get_de_app_version 'init' 'upstart' '3' )
5588                 elif [[ -n $( type -p epoch ) ]];then
5589                         init_type='Epoch'
5590                         # epoch version == Epoch Init System 1.0.1 "Sage"
5591                         init_version=$( get_de_app_version 'epoch' '^Epoch' '4' )
5592                 # missing data: 
5593                 # http://smarden.org/runit/sv.8.html
5594                 elif [[ -e /sbin/runit-init || -e /etc/runit || -n $( type -p sv ) ]];then
5595                         init_type='runit' # lower case
5596                         # no data on version yet
5597                 elif [[ -f /etc/inittab ]];then
5598                         init_type='SysVinit'
5599                         if [[ -n $( type -p strings ) ]];then
5600                                 strings_init_version="$( strings /sbin/init | grep -E 'version[[:space:]]+[0-9]' )"
5601                         fi
5602                         if [[ -n $strings_init_version ]];then
5603                                 init_version=$( gawk '{print $2}' <<< "$strings_init_version" )
5604                         fi
5605                 # freebsd at least
5606                 elif [[ -f /etc/ttys ]];then
5607                         init_type='init (bsd)'
5608                 fi
5609                 
5610                 if [[ -n $( grep 'openrc' <<< "$ls_run" ) ]];then
5611                         rc_type='OpenRC'
5612                         # /sbin/openrc --version == openrc (OpenRC) 0.13
5613                         if [[ -n $( type -p openrc ) ]];then
5614                                 rc_version=$( get_de_app_version 'openrc' '^openrc' '3' )
5615                         # /sbin/rc --version == rc (OpenRC) 0.11.8 (Gentoo Linux)
5616                         elif [[ -n $( type -p rc ) ]];then
5617                                 rc_version=$( get_de_app_version 'rc' '^rc' '3' )
5618                         fi
5619                 ## assume sysvrc, but this data is too buggy and weird and inconsistent to have meaning
5620                 # leaving this off for now
5621 #               elif [[ -f /etc/inittab ]];then
5622 #                       rc_type='SysVrc'
5623 #                       # this is a guess that rc and init are same versions, may need updates / fixes
5624 #                       rc_version=$init_version
5625                 fi
5626         fi
5627         
5628         IFS=$'\n'
5629         
5630         A_INIT_DATA=( 
5631         "$init_type"
5632         "$init_version"
5633         "$rc_type"
5634         "$rc_version"
5635         "$runlevel"
5636         "$default_runlevel" )
5637         
5638         IFS="$ORIGINAL_IFS"
5639         
5640         temp_array=${A_INIT_DATA[@]}
5641         log_function_data "A_INIT_DATA: $temp_array"
5642         
5643         eval $LOGFE
5644 }
5645
5646 get_kernel_version()
5647 {
5648         eval $LOGFS
5649         
5650         local kernel_version='' ksplice_kernel_version=''
5651         
5652         kernel_version=$( uname -rm )
5653         
5654         if [[ -n $( type -p uptrack-uname ) && -n $kernel_version ]];then
5655                 ksplice_kernel_version=$( uptrack-uname -rm )
5656                 if [[ $kernel_version != $ksplice_kernel_version ]];then
5657                         kernel_version="$ksplice_kernel_version (ksplice)"
5658                 fi
5659         fi
5660         log_function_data "kernel_version: $kernel_version - ksplice_kernel_version: $ksplice_kernel_version"
5661         
5662         echo $kernel_version
5663         
5664         eval $LOGFE
5665 }
5666
5667 # args: $1 - v/n 
5668 get_lspci_data()
5669 {
5670         eval $LOGFS
5671         local lspci_data=''
5672
5673         if [[ $B_LSPCI == 'true' ]];then
5674                 lspci_data="$( lspci -$1 | gawk '{
5675                         gsub(/\(prog-if[^)]*\)/,"")
5676                         sub(/^0000:/, "", $0) # seen case where the 0000: is prepended, rare, but happens
5677                         print
5678                 }' )"
5679         fi
5680         
5681         echo "$lspci_data"
5682         log_function_data 'raw' "lspci_data $1:\n$lspci_data"
5683         eval $LOGFE
5684 }
5685
5686 # args: $1 - busid
5687 get_lspci_chip_id()
5688 {
5689         eval $LOGFS
5690         
5691         local chip_id=''
5692         
5693         chip_id=$( gawk '
5694         /^'$1'/ {
5695                 if ( $3 != "" ) {
5696                         print $3
5697                 }
5698         }' <<< "$Lspci_n_Data" )
5699         
5700         echo $chip_id
5701         
5702         eval $LOGFE
5703 }
5704
5705 get_machine_data()
5706 {
5707         eval $LOGFS
5708         local temp_array='' separator='' id_file='' file_data='' array_string=''
5709         local id_dir='/sys/class/dmi/id/' dmi_data='' 
5710         local machine_files="
5711         sys_vendor product_name product_version product_serial product_uuid 
5712         board_vendor board_name board_version board_serial 
5713         bios_vendor bios_version bios_date 
5714         "
5715
5716         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
5717                 machine_files="$machine_files
5718                 chassis_vendor chassis_type chassis_version chassis_serial
5719                 "
5720         fi
5721         if [[ -d $id_dir ]];then
5722                 for id_file in $machine_files
5723                 do
5724                         file_data=''
5725                         if [[ -r $id_dir$id_file ]];then
5726                                 file_data=$( gawk '
5727                                 BEGIN {
5728                                         IGNORECASE=1
5729                                 }
5730                                 {
5731                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
5732                                         gsub(/,/, " ", $0)
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                                         sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", $0) 
5739                                         gsub(/bios|acpi/, "", $0)
5740                                         sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
5741                                         gsub(/^ +| +$/, "", $0)
5742                                         gsub(/ [ \t]+/, " ", $0)
5743                                         print $0
5744                                 }' < $id_dir$id_file )
5745                         fi
5746                         array_string="$array_string$separator$file_data"
5747                         separator=','
5748                 done
5749         else
5750                 get_dmidecode_data
5751                 if [[ -n $DMIDECODE_DATA ]];then
5752                         if [[ $B_ROOT == 'true' ]];then
5753                                 # this handles very old systems, like Lenny 2.6.26, with dmidecode, but no data
5754                                 if [[ -n $( grep -i 'no smbios ' <<< "$DMIDECODE_DATA" ) ]];then
5755                                         array_string='dmidecode-no-smbios-dmi-data'
5756                                 # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
5757                                 else
5758                                         array_string=$( gawk -F ':' '
5759                                         BEGIN {
5760                                                 IGNORECASE=1
5761                                                 baseboardManufacturer=""
5762                                                 baseboardProductName=""
5763                                                 baseboardSerialNumber=""
5764                                                 baseboardVersion=""
5765                                                 biosReleaseDate=""
5766                                                 biosRevision="" # only available from dmidecode
5767                                                 biosRomSize="" # only available from dmidecode
5768                                                 biosVendor=""
5769                                                 biosVersion=""
5770                                                 chassisManufacturer=""
5771                                                 chassisSerialNumber=""
5772                                                 chassisType=""
5773                                                 chassisVersion=""
5774                                                 systemManufacturer=""
5775                                                 systemProductName=""
5776                                                 systemVersion=""
5777                                                 systemSerialNumber=""
5778                                                 systemUuid=""
5779                                                 bItemFound="" # we will only output if at least one item was found
5780                                                 fullString=""
5781                                                 testString=""
5782                                                 bSys=""
5783                                                 bCha=""
5784                                                 bBio=""
5785                                                 bBas=""
5786                                         }
5787                                         /^Bios Information/ {
5788                                                 while ( getline && !/^$/ ) {
5789                                                         if ( $1 ~ /^Release Date/ ) { biosReleaseDate=$2 }
5790                                                         if ( $1 ~ /^BIOS Revision/ ) { biosRevision=$2 }
5791                                                         if ( $1 ~ /^ROM Size/ ) { biosRomSize=$2 }
5792                                                         if ( $1 ~ /^Vendor/ ) { biosVendor=$2 }
5793                                                         if ( $1 ~ /^Version/ ) { biosVersion=$2 }
5794                                                 }
5795                                                 testString=biosReleaseDate biosRevision biosRomSize biosVendor biosVersion
5796                                                 if ( testString != ""  ) {
5797                                                         bItemFound="true"
5798                                                 }
5799                                                 bBio="true"
5800                                         }
5801                                         /^Base Board Information/ {
5802                                                 while ( getline && !/^$/ ) {
5803                                                         if ( $1 ~ /^Manufacturer/ ) { baseboardManufacturer=$2 }
5804                                                         if ( $1 ~ /^Product Name/ ) { baseboardProductName=$2 }
5805                                                         if ( $1 ~ /^Serial Number/ ) { baseboardSerialNumber=$2 }
5806                                                 }
5807                                                 testString=baseboardManufacturer baseboardProductName baseboardSerialNumber
5808                                                 if ( testString != ""  ) {
5809                                                         bItemFound="true"
5810                                                 }
5811                                                 bBas="true"
5812                                         }
5813                                         /^Chassis Information/ {
5814                                                 while ( getline && !/^$/ ) {
5815                                                         if ( $1 ~ /^Manufacturer/ ) { chassisManufacturer=$2 }
5816                                                         if ( $1 ~ /^Serial Number/ ) { chassisSerialNumber=$2 }
5817                                                         if ( $1 ~ /^Type/ ) { chassisType=$2 }
5818                                                         if ( $1 ~ /^Version/ ) { chassisVersion=$2 }
5819                                                 }
5820                                                 testString=chassisManufacturer chassisSerialNumber chassisType chassisVersion
5821                                                 if ( testString != ""  ) {
5822                                                         bItemFound="true"
5823                                                 }
5824                                                 bCha="true"
5825                                         }
5826                                         /^System Information/ {
5827                                                 while ( getline && !/^$/ ) {
5828                                                         if ( $1 ~ /^Manufacturer/ ) { systemManufacturer=$2 }
5829                                                         if ( $1 ~ /^Product Name/ ) { systemProductName=$2 }
5830                                                         if ( $1 ~ /^Version/ ) { systemVersion=$2 }
5831                                                         if ( $1 ~ /^Serial Number/ ) { systemSerialNumber=$2 }
5832                                                         if ( $1 ~ /^UUID/ ) { systemUuid=$2 }
5833                                                 }
5834                                                 testString=systemManufacturer systemProductName systemVersion systemSerialNumber systemUuid
5835                                                 if ( testString != ""  ) {
5836                                                         bItemFound="true"
5837                                                 }
5838                                                 bSys="true"
5839                                         }
5840                                         ( bSys == "true" && bCha="true" && bBio == "true" && bBas == "true" ) {
5841                                                 exit # stop the loop
5842                                         }
5843                                         END {
5844                                                 if ( bItemFound == "true" ) {
5845                                                         fullString = systemManufacturer "," systemProductName "," systemVersion "," systemSerialNumber 
5846                                                         fullString = fullString "," systemUuid "," baseboardManufacturer "," baseboardProductName 
5847                                                         fullString = fullString "," baseboardVersion "," baseboardSerialNumber "," biosVendor
5848                                                         fullString = fullString "," biosVersion "," biosReleaseDate "," chassisManufacturer
5849                                                         fullString = fullString "," chassisType "," chassisVersion "," chassisSerialNumber 
5850                                                         fullString = fullString ","  biosRevision "," biosRomSize
5851                                                         
5852                                                         print fullString
5853                                                 }
5854                                         }' <<< "$DMIDECODE_DATA" )
5855                                 fi
5856                         else
5857                                 array_string='dmidecode-non-root-user'
5858                         fi
5859                 fi
5860         fi
5861         IFS=','
5862         A_MACHINE_DATA=( $array_string )
5863         IFS="$ORIGINAL_IFS"
5864         temp_array=${A_MACHINE_DATA[@]}
5865 #       echo ${temp_array[@]}
5866         log_function_data "A_MACHINE_DATA: $temp_array"
5867         eval $LOGFE
5868 }
5869 # B_ROOT='true';get_machine_data;exit
5870 ## return memory used/installed
5871 get_memory_data()
5872 {
5873         eval $LOGFS
5874         local memory='' memory_full='' 
5875         if [[ $B_MEMINFO_FILE == 'true' ]];then
5876                 memory=$( gawk '
5877                 /^MemTotal:/ {
5878                         tot = $2
5879                 }
5880                 /^(MemFree|Buffers|Cached):/ {
5881                         notused+=$2
5882                 }
5883                 END {
5884                         used = tot - notused
5885                         printf("%.1f/%.1fMB\n", used/1024, tot/1024)
5886                 }' $FILE_MEMINFO )
5887                 log_function_data 'cat' "$FILE_MEMINFO"
5888         elif [[ $B_SYSCTL == 'true' && -n $Sysctl_a_Data ]];then
5889                 local gawk_fs=': '
5890         
5891                 if [[ $BSD_VERSION == 'openbsd' ]];then
5892                         gawk_fs='='
5893                 fi
5894                 memory=$( grep -i 'mem' <<< "$Sysctl_a_Data" | gawk -F "$gawk_fs"  '
5895                 BEGIN {
5896                         realMemory=""
5897                         freeMemory=""
5898                 }
5899                 # freebsd seems to use bytes here
5900                 /^hw.physmem/ {
5901                         gsub(/^[^0-9]+|[^0-9]+$/,"",$2)
5902                         realMemory = $2/1024
5903                         if ( freeMemory != "" ) {
5904                                 exit
5905                         }
5906                 }
5907                 # But, it uses K here. Openbsd does not seem to have this item
5908                 # this can be either: Free Memory OR Free Memory Pages
5909                 $1 ~ /^Free Memory/ {
5910                         gsub(/[^0-9]/,"",$NF)
5911                         freeMemory = $NF
5912                         if ( realMemory != "" ) {
5913                                 exit
5914                         }
5915                 }
5916                 END {
5917                         # hack: temp fix for openbsd: in case no free mem was detected but we have physmem
5918                         if ( freeMemory == "" && realMemory != "" ) {
5919                                 printf("NA/%.1fMB\n", realMemory/1024)
5920                         }
5921                         else if ( freeMemory != "" && realMemory != "" ) {
5922                                 used = realMemory - freeMemory
5923                                 printf("%.1f/%.1fMB\n", used/1024, realMemory/1024)
5924                         }
5925                 }' )
5926         fi
5927         echo "$memory"
5928         log_function_data "memory: $memory"
5929         eval $LOGFE
5930 }
5931
5932 # process and return module version data
5933 get_module_version_number()
5934 {
5935         eval $LOGFS
5936         local module_version=''
5937         
5938         if [[ $B_MODINFO_TESTED != 'true' ]];then
5939                 B_MODINFO_TESTED='true'
5940                 MODINFO_PATH=$( type -p modinfo )
5941         fi
5942
5943         if [[ -n $MODINFO_PATH ]];then
5944                 module_version=$( $MODINFO_PATH $1 2>/dev/null | gawk '
5945                 BEGIN {
5946                         IGNORECASE=1
5947                 }
5948                 /^version/ {
5949                         gsub(/,/, " ", $2)
5950                         gsub(/^ +| +$/, "", $2)
5951                         gsub(/ [ \t]+/, " ", $2)
5952                         print $2
5953                 }
5954                 ' )
5955         fi
5956
5957         echo "$module_version"
5958         log_function_data "module_version: $module_version"
5959         eval $LOGFE
5960 }
5961
5962 ## create array of network cards
5963 get_networking_data()
5964 {
5965         eval $LOGFS
5966         
5967         local B_USB_NETWORKING='false' temp_array=''
5968         
5969         IFS=$'\n'
5970         A_NETWORK_DATA=( $( 
5971         echo "$Lspci_v_Data" | gawk '
5972         BEGIN {
5973                 IGNORECASE=1
5974                 counter=0 # required to handle cases of > 1 instance of the same chipset
5975         }
5976         /^[0-9a-f:\.]+ (ethernet|network) (controller|bridge)/ || /^[0-9a-f:\.]+ [^:]+: .*(ethernet|network).*$/ {
5977                 nic=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
5978                 #gsub(/realtek semiconductor/, "Realtek", nic)
5979                 #gsub(/davicom semiconductor/, "Davicom", nic)
5980                 # The doublequotes are necessary because of the pipes in the variable.
5981                 gsub(/'"$BAN_LIST_NORMAL"'/, "", nic)
5982                 gsub(/,/, " ", nic)
5983                 gsub(/^ +| +$/, "", nic)
5984                 gsub(/ [ \t]+/, " ", nic)
5985                 # construct a unique string ending for each chipset detected, this allows for
5986                 # multiple instances of the same exact chipsets, ie, dual gigabit 
5987                 nic = nic "~~" counter++
5988                 aPciBusId[nic] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
5989                 # I do not understand why incrementing a string index makes sense? 
5990                 eth[nic]++ 
5991                 while ( getline && !/^$/ ) {
5992                         gsub(/,/, "", $0)
5993                         if ( /I\/O/ ) {
5994                                 ports[nic] = ports[nic] $4 " "
5995                         }
5996                         if ( /driver in use/ ) {
5997                                 drivers[nic] = drivers[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
5998                         }
5999                         else if ( /kernel modules/ ) {
6000                                 modules[nic] = modules[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
6001                         }
6002                 }
6003         }
6004
6005         END {
6006                 j=0
6007                 for (i in eth) {
6008                         useDrivers=""
6009                         usePorts=""
6010                         useModules=""
6011                         usePciBusId=""
6012
6013                         if ( eth[i] > 1 ) {
6014                                 a[j] = eth[i] "x " i
6015                         }
6016                         else {
6017                                 a[j] = i
6018                         }       
6019                         ## note: this loses the plural ports case, is it needed anyway?
6020                         if ( ports[i] != "" ) {
6021                                 usePorts = ports[i]
6022                         }
6023                         if ( drivers[i] != "" ) {
6024                                 useDrivers = drivers[i]
6025                         }
6026                         if ( modules[i] != "" ) {
6027                                 useModules = modules[i]
6028                         }
6029                         if ( aPciBusId[i] != "" ) {
6030                                 usePciBusId = aPciBusId[i]
6031                         }
6032                         # create array primary item for master array
6033                         # and strip out the counter again, this handled dual cards with same chipset
6034                         sub( /~~[0-9]+$/, "", a[j] )
6035                         sub( / $/, "", usePorts ) # clean off trailing whitespace
6036                         print a[j] "," useDrivers "," usePorts "," useModules, "," usePciBusId
6037                         j++
6038                 }
6039         }' ) )
6040         IFS="$ORIGINAL_IFS"
6041         get_networking_usb_data
6042         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' || $B_USB_NETWORKING == 'true' ]];then
6043                 get_network_advanced_data
6044         fi
6045         temp_array=${A_NETWORK_DATA[@]}
6046         log_function_data "A_NETWORK_DATA: $temp_array"
6047         
6048         eval $LOGFE
6049 }
6050
6051 get_network_advanced_data()
6052 {
6053         eval $LOGFS
6054         local a_network_adv_working='' if_path='' working_path='' working_uevent_path='' dir_path=''
6055         local if_id='' speed='' duplex='' mac_id='' oper_state=''  chip_id=''
6056         local usb_data='' usb_vendor='' usb_product='' product_path='' driver_test=''
6057         
6058         for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
6059         do
6060                 IFS=","
6061                 a_network_adv_working=( ${A_NETWORK_DATA[i]} )
6062                 # reset these every go round
6063                 driver_test=''
6064                 if_id='' 
6065                 speed='' 
6066                 duplex='' 
6067                 mac_id='' 
6068                 oper_state=''
6069                 usb_data=''
6070                 chip_id=''
6071                 if [[ -z $( grep '^usb-' <<< ${a_network_adv_working[4]} ) ]];then
6072                         # note although this may exist technically don't use it, it's a virtual path
6073                         # and causes weird cat errors when there's a missing file as well as a virtual path
6074                         # /sys/bus/pci/devices/0000:02:02.0/net/eth1
6075                         # real paths are: /sys/devices/pci0000:00/0000:00:1e/0/0000:02:02.0/net/eth1/uevent
6076                         # and on older debian kernels: /sys/devices/pci0000:00/0000:02:02.0/net:eth1/uevent
6077                         # but broadcom shows this sometimes:
6078                         # /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ssb0:0/uevent:['DRIVER=b43', 'MODALIAS=ssb:v4243id0812rev0D']:
6079                         working_path="/sys/bus/pci/devices/0000:${a_network_adv_working[4]}"
6080                         # now we want the real one, that xiin also displays, without symbolic links.
6081                         if [[ -e $working_path ]];then
6082                                 working_path=$( readlink -f $working_path 2>/dev/null )
6083                                 # sometimes there is another directory between the path and /net
6084                                 if [[ ! -e $working_path/net ]];then
6085                                         # using find here, probably will need to also use it in usb part since the grep
6086                                         # method seems to not be working now. Slice off the rest, which leaves the basic path
6087                                         working_path=$( find $working_path/*/net/*/uevent 2>/dev/null | \
6088                                         sed 's|/net.*||' )
6089                                 fi
6090                         fi
6091                         # working_path=$( ls /sys/devices/pci*/*/0000:${a_network_adv_working[4]}/net/*/uevent  )
6092                 else
6093                         # now we'll use the actual vendor:product string instead
6094                         usb_data=${a_network_adv_working[10]}
6095                         usb_vendor=$( cut -d ':' -f 1 <<< $usb_data )
6096                         usb_product=$( cut -d ':' -f 2 <<< $usb_data )
6097                         # this grep returns the path plus the contents of the file, with a colon separator, so slice that off
6098                         # /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/idVendor
6099                         working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/*/idVendor | \
6100                         sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
6101                         # try an alternate path if first one doesn't work
6102                         # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/idVendor
6103                         if [[ -z $working_path ]];then
6104                                 working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/idVendor | \
6105                                 sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
6106                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/idProduct | \
6107                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
6108                         else
6109                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/*/idProduct | \
6110                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
6111                         fi
6112                         
6113                         # make sure it's the right product/vendor match here, it will almost always be but let's be sure
6114                         if [[ -n $working_path && -n $product_path ]] && [[ $working_path == $product_path ]];then
6115                         #if [[ -n $working_path ]];then
6116                                 # now ls that directory and get the numeric starting sub directory and that should be the full path
6117                                 # to the /net directory part
6118                                 dir_path=$( ls ${working_path} 2>/dev/null | grep -sE '^[0-9]' )
6119                                 working_uevent_path="${working_path}${dir_path}"
6120                         fi
6121                 fi
6122                 # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/uevent grep for DRIVER=
6123                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/1-1:1.0/uevent
6124                 if [[ -n $usb_data ]];then
6125                         driver_test=$( grep -si 'DRIVER=' $working_uevent_path/uevent | cut -d '=' -f 2 )
6126                         if [[ -n $driver_test ]];then
6127                                 a_network_adv_working[1]=$driver_test
6128                         fi
6129                 fi
6130                 log_function_data "PRE: working_path: $working_path\nworking_uevent_path: $working_uevent_path"
6131                 
6132                 # this applies in two different cases, one, default, standard, two, for usb, this is actually
6133                 # the short path, minus the last longer numeric directory name, ie: 
6134                 # from debian squeeze 2.6.32-5-686: 
6135                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/net/wlan0/address
6136                 if [[ -e $working_path/net ]];then
6137                         if_path=$( ls $working_path/net 2>/dev/null )
6138                         if_id=$if_path
6139                         working_path=$working_path/net/$if_path
6140                 # this is the normal usb detection if the first one didn't work
6141                 elif [[ -n $usb_data && -e $working_uevent_path/net ]];then
6142                         if_path=$( ls $working_uevent_path/net 2>/dev/null )
6143                         if_id=$if_path
6144                         working_path=$working_uevent_path/net/$if_path
6145                 # 2.6.32 debian lenny kernel shows not: /net/eth0 but /net:eth0
6146                 else
6147                         if_path=$( ls $working_path 2>/dev/null | grep 'net:' )
6148                         if_id=$( cut -d ':' -f 2 <<< "$if_path" )
6149                         working_path=$working_path/$if_path
6150                 fi
6151                 log_function_data "POST: working_path: $working_path\nif_path: $if_path - if_id: $if_id"
6152                 
6153                 if [[ -n $if_path ]];then
6154                         if [[ -r $working_path/speed ]];then
6155                                 speed=$( cat $working_path/speed 2>/dev/null )
6156                         fi
6157                         if [[ -r $working_path/duplex ]];then
6158                                 duplex=$( cat $working_path/duplex 2>/dev/null )
6159                         fi
6160                         if [[ -r $working_path/address ]];then
6161                                 mac_id=$( cat $working_path/address 2>/dev/null )
6162                         fi
6163                         if [[ -r $working_path/operstate ]];then
6164                                 oper_state=$( cat $working_path/operstate 2>/dev/null )
6165                         fi
6166                 fi
6167                 
6168                 if [[ -n ${a_network_adv_working[10]} ]];then
6169                         chip_id=${a_network_adv_working[10]}
6170                 fi
6171                 A_NETWORK_DATA[i]=${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
6172                 IFS="$ORIGINAL_IFS"
6173         done
6174
6175         eval $LOGFE
6176 }
6177
6178 get_networking_usb_data()
6179 {
6180         eval $LOGFS
6181         local lsusb_path='' lsusb_data='' a_usb='' array_count=''
6182         
6183         # now we'll check for usb wifi, a work in progress
6184         # USB_NETWORK_SEARCH
6185         # alsa usb detection by damentz
6186         # for every sound card symlink in /proc/asound - display information about it
6187         lsusb_path=$( type -p lsusb )
6188         # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue
6189         if [[ -n $lsusb_path ]]; then
6190                 # send error messages of lsusb to /dev/null as it will display a bunch if not a super user
6191                 lsusb_data="$( $lsusb_path 2>/dev/null )"
6192                 # also, find the contents of usbid in lsusb and print everything after the 7th word on the
6193                 # corresponding line. Finally, strip out commas as they will change the driver :)
6194                 if [[ -n $lsusb_data ]];then
6195                         IFS=$'\n'
6196                         a_usb=( $( 
6197                         gawk '
6198                         BEGIN {
6199                                 IGNORECASE=1
6200                                 string=""
6201                                 separator=""
6202                         }
6203                         /'"$USB_NETWORK_SEARCH"'/ && !/bluetooth| hub|keyboard|mouse|printer| ps2|reader|scan|storage/ {
6204                                 string=""
6205                                 gsub( /,/, " ", $0 )
6206                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
6207                                 gsub(/ [ \t]+/, " ", $0)
6208                                 #sub(/realtek semiconductor/, "Realtek", $0)
6209                                 #sub(/davicom semiconductor/, "Davicom", $0)
6210                                 #sub(/Belkin Components/, "Belkin", $0)
6211                                 
6212                                 for ( i=7; i<= NF; i++ ) {
6213                                         string = string separator $i
6214                                         separator = " "
6215                                 }
6216                                 if ( $2 != "" ){
6217                                         sub(/:/, "", $4 )
6218                                         print string ",,,,usb-" $2 "-" $4 ",,,,,," $6
6219                                 }
6220                         }' <<< "$lsusb_data" ) )
6221                         IFS="$ORIGINAL_IFS"
6222                         if [[ ${#a_usb[@]} -gt 0 ]];then
6223                                 array_count=${#A_NETWORK_DATA[@]}
6224                                 for (( i=0; i < ${#a_usb[@]}; i++ ))
6225                                 do
6226                                         A_NETWORK_DATA[$array_count]=${a_usb[i]}
6227                                         ((array_count++))
6228                                 done
6229                                 # need this to get the driver data for -N regular output, but no need
6230                                 # to run the advanced stuff unless required
6231                                 B_USB_NETWORKING='true'
6232                         fi
6233                 fi
6234         fi
6235 #       echo $B_USB_NETWORKING
6236         eval $LOGFE
6237 }
6238
6239 get_networking_wan_ip_data()
6240 {
6241         eval $LOGFS
6242         local ip=''
6243
6244         # get ip using wget redirect to stdout. This is a clean, text only IP output url,
6245         # single line only, ending in the ip address. May have to modify this in the future
6246         # to handle ipv4 and ipv6 addresses but should not be necessary.
6247         # awk has bad regex handling so checking it with grep -E instead
6248         # ip=$( echo  2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk  --re-interval '
6249         # ip=$( wget -q -O - $WAN_IP_URL | gawk  --re-interval '
6250         ip=$( wget -t 1 -T $WGET_TIMEOUT -q -O - $WAN_IP_URL | gawk  --re-interval '
6251         {
6252                 #gsub("\n","",$2")
6253                 print $NF
6254         }' )
6255         # validate the data
6256         if [[ -z $ip ]];then
6257                 ip='None Detected!'
6258         elif [[ -z $( grep -Es \
6259         '^([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
6260                 ip='IP Source Corrupt!'
6261         fi
6262         echo "$ip"
6263         log_function_data "ip: $ip"
6264         eval $LOGFE
6265 }
6266
6267 get_networking_local_ip_data()
6268 {
6269         eval $LOGFS
6270         
6271         local ip_tool_command=$( type -p ip )
6272         local temp_array='' ip_tool='ip' ip_tool_data=''
6273         # the chances for all new systems to have ip by default are far higher than
6274         # the deprecated ifconfig. Only try for ifconfig if ip is not present in system
6275         if [[ -z $ip_tool_command ]];then
6276                 ip_tool_command=$( type -p ifconfig )
6277                 ip_tool='ifconfig'
6278         else
6279                 ip_tool_command="$ip_tool_command addr"
6280         fi
6281         if [[ -n "$ip_tool_command" ]];then
6282                 if [[ $ip_tool == 'ifconfig' ]];then
6283                         ip_tool_data="$( $ip_tool_command | gawk '
6284                         {
6285                                 line=gensub(/^([a-z]+[0-9][:]?[[:space:]].*)/, "\n\\1", $0)
6286                                 print line
6287                         }' )"
6288                 # note, ip addr does not have proper record separation, so creating new lines explicitly here at start
6289                 # of each IF record item. Also getting rid of the unneeded numeric line starters, now it can be parsed 
6290                 # like ifconfig more or less
6291                 elif [[ $ip_tool == 'ip' ]];then
6292                         ip_tool_data="$( eval ${ip_tool_command} | sed 's/^[0-9]\+:[[:space:]]\+/\n/' )"
6293                 fi
6294         fi
6295         if [[ -z $ip_tool_command ]];then
6296                 A_INTERFACES_DATA=( "Interfaces program 'ip' missing. Please check: $SCRIPT_NAME --recommends" )
6297         elif [[ -n "$ip_tool_data" ]];then
6298                 IFS=$'\n' # $ip_tool_command
6299                 A_INTERFACES_DATA=( $( 
6300                 gawk -v ipTool=$ip_tool -v bsdType=$BSD_TYPE '
6301                 BEGIN {
6302                         IGNORECASE=1
6303                         interface=""
6304                         ifIp=""
6305                         ifIpV6=""
6306                         ifMask=""
6307                 }
6308                 # skip past the lo item
6309                 /^lo/ {
6310                         while (getline && !/^$/ ) {
6311                                 # do nothing, just get past this entry item
6312                         }
6313                 }
6314                 /^[a-zA-Z]+[0-9]/ {
6315                         # not clear on why inet is coming through, but this gets rid of it
6316                         # as first line item.
6317                         gsub(/,/, " ", $0)
6318                         gsub(/^ +| +$/, "", $0)
6319                         gsub(/ [ \t]+/, " ", $0)
6320                         interface = $1
6321                         # prep this this for ip addr: eth0: 
6322                         sub(/:/, "", interface)
6323                         ifIp=""
6324                         ifIpV6=""
6325                         ifMask=""
6326                         aInterfaces[interface]++
6327
6328                         while (getline && !/^$/ ) {
6329                                 if ( ipTool == "ifconfig" ) {
6330                                         if (/inet addr:/) {
6331                                                 ifIp = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 )
6332                                                 if (/mask:/) {
6333                                                         ifMask = gensub( /mask:([0-9\.]+)/, "\\1", "g", $NF )
6334                                                 }
6335                                         }
6336                                         if (/inet6 addr:/) {
6337                                                 ifIpV6 = $3
6338                                         }
6339                                         if ( bsdType == "bsd" ) {
6340                                                 if ( $1 == "inet" ) {
6341                                                         ifIp = $2
6342                                                         if ( $3 == "netmask" ) {
6343                                                                 ifMask = $4
6344                                                         }
6345                                                 }
6346                                                 if ( $0 ~ /inet6.*%/ ) {
6347                                                         sub(/%.*/,"",$2)
6348                                                         ifIpV6 = $2
6349                                                 }
6350                                         }
6351                                 }
6352                                 else if ( ipTool == "ip" ) {
6353                                         if ( $1 == "inet" ) {
6354                                                 ifIp = $2
6355                                         }
6356                                         if ( $1 == "inet6" ) {
6357                                                 ifIpV6 = $2
6358                                         }
6359                                 }
6360                         }
6361                         # slice off the digits that are sometimes tacked to the end of the address, 
6362                         # like: /64 or /24
6363                         sub(/\/[0-9]+/, "", ifIp)
6364                         sub(/\/[0-9]+/, "", ifIpV6)
6365                         ipAddresses[interface] = ifIp "," ifMask "," ifIpV6
6366                 }
6367                 END {
6368                         j=0
6369                         for (i in aInterfaces) {
6370                                 ifData = ""
6371                                 a[j] = i
6372                                 if (ipAddresses[i] != "") {
6373                                         ifData = ipAddresses[i]
6374                                 }
6375                                 # create array primary item for master array
6376                                 # tested needed to avoid bad data from above, if null it is garbage
6377                                 # this is the easiest way to handle junk I found, improve if you want
6378                                 if ( ifData != "" ) {
6379                                         print a[j] "," ifData
6380                                 }
6381                                 j++
6382                         }
6383                 }' <<< "$ip_tool_data" ) )
6384                 IFS="$ORIGINAL_IFS"
6385         else
6386                 A_INTERFACES_DATA=( "Interfaces program $ip_tool present but created no data. " )
6387         fi
6388         temp_array=${A_INTERFACES_DATA[@]}
6389         log_function_data "A_INTERFACES_DATA: $temp_array"
6390         eval $LOGFE
6391 }
6392 # get_networking_local_ip_data;exit
6393
6394 # get_networking_local_ip_data;exit
6395 get_optical_drive_data()
6396 {
6397         eval $LOGFS
6398         
6399         local temp_array='' sys_uevent_path='' proc_cdrom='' link_list=''
6400         local separator='' linked='' disk='' item_string='' proc_info_string='' 
6401         local dev_disks_links="$( ls /dev/dvd* /dev/cd* /dev/scd* 2>/dev/null  )"
6402         # get the actual disk dev location, first try default which is easier to run, need to preserve line breaks
6403         local dev_disks_real="$( echo "$dev_disks_links" | xargs -L 1 readlink 2>/dev/null | sort -u )"
6404         # Some systems don't support xargs -L so we need to do it manually
6405         if [[ -z $dev_disks_real ]];then
6406                 for linked in $dev_disks_links
6407                 do
6408                         disk=$( readlink $linked 2>/dev/null )
6409                         if [[ -n $disk ]];then
6410                                 disk=$( basename $disk ) # puppy shows this as /dev/sr0, not sr0
6411                                 if [[ -z $dev_disks_real || -z $( grep $disk <<< $dev_disks_real ) ]];then
6412                                         # need line break IFS for below, no white space
6413                                         dev_disks_real="$dev_disks_real$separator$disk"
6414                                         separator=$'\n'
6415                                 fi
6416                         fi
6417                 done
6418                 dev_disks_real="$( sort -u <<< "$dev_disks_real" )"
6419                 linked=''
6420                 disk=''
6421                 separator=''
6422         fi
6423
6424         # A_OPTICAL_DRIVE_DATA indexes: not going to use all these, but it's just as easy to build the full
6425         # data array and use what we need from it as to update it later to add features or items
6426         # 0 - true dev path, ie, sr0, hdc
6427         # 1 - dev links to true path
6428         # 2 - device vendor - for hdx drives, vendor model are one string from proc
6429         # 3 - device model
6430         # 4 - device rev version
6431         # 5 - speed
6432         # 6 - multisession support
6433         # 7 - MCN support
6434         # 8 - audio read
6435         # 9 - cdr
6436         # 10 - cdrw
6437         # 11 - dvd read
6438         # 12 - dvdr
6439         # 13 - dvdram
6440         # 14 - state
6441
6442         if [[ -n $dev_disks_real ]];then
6443                 if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
6444                         proc_cdrom="$( cat /proc/sys/dev/cdrom/info 2>/dev/null )"
6445                 fi
6446                 IFS=$'\n'
6447                 A_OPTICAL_DRIVE_DATA=( $(
6448                 for disk in $dev_disks_real
6449                 do
6450                         for linked in $dev_disks_links 
6451                         do
6452                                 if [[ -n $( readlink $linked | grep $disk ) ]];then
6453                                         linked=$( basename $linked )
6454                                         link_list="$link_list$separator$linked"
6455                                         separator='~'
6456                                 fi
6457                         done
6458                         item_string="$disk,$link_list"
6459                         link_list=''
6460                         linked=''
6461                         separator=''
6462                         vendor=''
6463                         model=''
6464                         proc_info_string=''
6465                         rev_number=''
6466                         state=""
6467                         sys_path=''
6468                         # this is only for new sd type paths in /sys, otherwise we'll use /proc/ide
6469                         if [[ -z $( grep '^hd' <<< $disk ) ]];then
6470                                 sys_path=$( ls /sys/devices/pci*/*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
6471                                 # no need to test for errors yet, probably other user systems will require some alternate paths though
6472                                 if [[ -n $sys_path ]];then
6473                                         vendor=$( cat $sys_path/vendor 2>/dev/null )
6474                                         model=$( cat $sys_path/model 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6475                                         state=$( cat $sys_path/state 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6476                                         rev_number=$( cat $sys_path/rev 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6477                                 fi
6478                         elif [[ -e /proc/ide/$disk/model ]];then
6479                                 vendor=$( cat /proc/ide/$disk/model 2>/dev/null )
6480                         fi
6481                         if [[ -n $vendor ]];then
6482                                 vendor=$( gawk '
6483                                 BEGIN {
6484                                         IGNORECASE=1
6485                                 }
6486                                 {
6487                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
6488                                         sub(/TSSTcorp/, "TSST ", $0) # seen more than one of these weird ones
6489                                         gsub(/,/, " ", $0)
6490                                         gsub(/^[[:space:]]*|[[:space:]]*$/, "", $0)
6491                                         gsub(/ [[:space:]]+/, " ", $0)
6492                                         print $0
6493                                 }'      <<< $vendor )
6494                         fi
6495                         # this needs to run no matter if there's proc data or not to create the array comma list
6496                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
6497                                 proc_info_string=$( gawk -v diskId=$disk '
6498                                 BEGIN {
6499                                         IGNORECASE=1
6500                                         position=""
6501                                         speed=""
6502                                         multisession=""
6503                                         mcn=""
6504                                         audio=""
6505                                         cdr=""
6506                                         cdrw=""
6507                                         dvd=""
6508                                         dvdr=""
6509                                         dvdram=""
6510                                 }
6511                                 # first get the position of the device name from top field
6512                                 # we will use this to get all the other data for that column
6513                                 /drive name:/ {
6514                                         for ( position=3; position <= NF; position++ ) {
6515                                                 if ( $position == diskId ) {
6516                                                         break
6517                                                 }
6518                                         }
6519                                 }
6520                                 /drive speed:/ {
6521                                         speed = $position
6522                                 }
6523                                 /Can read multisession:/ {
6524                                         multisession=$( position + 1 )
6525                                 }
6526                                 /Can read MCN:/ {
6527                                         mcn=$( position + 1 )
6528                                 }
6529                                 /Can play audio:/ {
6530                                         audio=$( position + 1 )
6531                                 }
6532                                 /Can write CD-R:/ {
6533                                         cdr=$( position + 1 )
6534                                 }
6535                                 /Can write CD-RW:/ {
6536                                         cdrw=$( position + 1 )
6537                                 }
6538                                 /Can read DVD:/ {
6539                                         dvd=$( position + 1 )
6540                                 }
6541                                 /Can write DVD-R:/ {
6542                                         dvdr=$( position + 1 )
6543                                 }
6544                                 /Can write DVD-RAM:/ {
6545                                         dvdram=$( position + 1 )
6546                                 }
6547                                 END {
6548                                         print speed "," multisession "," mcn "," audio "," cdr "," cdrw "," dvd "," dvdr "," dvdram
6549                                 }
6550                                 ' <<< "$proc_cdrom" )
6551                         fi
6552                         item_string="$item_string,$vendor,$model,$rev_number,$proc_info_string,$state"
6553                         echo $item_string
6554                 done \
6555                 ) )
6556                 IFS="$ORIGINAL_IFS"
6557         fi
6558         temp_array=${A_OPTICAL_DRIVE_DATA[@]}
6559         log_function_data "A_OPTICAL_DRIVE_DATA: $temp_array"
6560         eval $LOGFE
6561 }
6562
6563 get_partition_data()
6564 {
6565         eval $LOGFS
6566         
6567         local a_partition_working='' dev_item='' temp_array='' dev_working_item='' 
6568         local swap_data='' df_string='' main_partition_data='' df_test='' fs_type=''
6569         local mount_data='' dev_bsd_item=''
6570         #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660'
6571         # df doesn't seem to work in script with variables like at the command line
6572         # added devfs linprocfs sysfs fdescfs which show on debian kfreebsd kernel output
6573         if [[ -z $BSD_TYPE ]];then
6574                 swap_data="$( swapon -s 2>/dev/null )"
6575                 df_string='df -h -T -P --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
6576                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs
6577                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs'
6578         else
6579                 swap_data="$( swapctl -l 2>/dev/null )"
6580                 # default size is 512, -H only for size in human readable format
6581                 # older bsds don't support -T, pain, so we'll use partial output there
6582                 df_test=$( df -H -T 2>/dev/null )
6583                 if [[ -n $df_test ]];then
6584                         df_string='df -H -T'
6585                 else
6586                         df_string='df -H'
6587                 fi
6588         fi
6589         main_partition_data="$( eval $df_string )"
6590         # set dev disk label/mapper/uuid data globals
6591         get_partition_dev_data 'label'
6592         get_partition_dev_data 'mapper'
6593         get_partition_dev_data 'uuid'
6594         
6595         log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data"
6596         
6597         # new kernels/df have rootfs and / repeated, creating two entries for the same partition
6598         # so check for two string endings of / then slice out the rootfs one, I could check for it
6599         # before slicing it out, but doing that would require the same action twice re code execution
6600         if [[ $( grep -cs '[[:space:]]/$' <<< "$main_partition_data" ) -gt 1 ]];then
6601                 main_partition_data="$( grep -vs '^rootfs' <<< "$main_partition_data" )"
6602         fi
6603         log_function_data 'raw' "main_partition_data_post_rootfs:\n$main_partition_data\n\nswap_data:\n$swap_data"
6604         IFS=$'\n'
6605         # sample line: /dev/sda2     ext3     15G  8.9G  4.9G  65% /home
6606         # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used
6607         ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if
6608         ## the first field is too long, it will occupy its own line, this way we are getting only the needed data
6609         A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk -v bsdType=$BSD_TYPE '
6610         BEGIN {
6611                 IGNORECASE=1
6612                 fileSystem=""
6613         }
6614         # this has to be nulled for every iteration so it does not retain value from last iteration
6615         devBase=""
6616         # skipping these file systems because bsds do not support df --exclude-type=<fstype>
6617         # note that using $1 to handle older bsd df, which do not support -T. This will not be reliable but we will see
6618         ( bsdType != "" ) {
6619                 # skip if non disk/partition, or if raid primary id, which will not have a / in it
6620                 if ( $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|iso9660|linprocfs|procfs|squashfs|sysfs|tmpfs|type|unionfs)$/ || 
6621                 $1 ~ /^([^\/]+)$/ ) {
6622                         # note use next, not getline or it does not work right
6623                         next 
6624                 }
6625         }
6626         # this is required because below we are subtracting from NF, so it has to be > 5
6627         # the real issue is long file system names that force the wrap of df output: //fileserver/main
6628         # but we still need to handle more dynamically long space containing file names, but later.
6629         # Using df -P should fix this, ie, no wrapping of line lines, but leaving this for now
6630         ( NF < 6 ) && ( $0 !~ /[0-9]+%/ ) {
6631                 # set the dev location here for cases of wrapped output
6632                 if ( NF == 1 ) {
6633                         devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6634                 }
6635                 getline
6636         }
6637         
6638         # next set devBase if it didn not get set above here
6639         ( devBase == "" ) && ( $1 ~ /^\/dev\/|:\/|\/\// ) {
6640                 devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6641         }
6642         # this handles zfs type devices/partitions, which do not start with / but contain /
6643         ( bsdType != "" && devBase == "" && $1 ~ /^[^\/]+\/.+/ ) {
6644                 devBase=gensub( /^([^\/]+\/)([^\/]+)$/, "non-dev-\\1\\2", 1, $1 )
6645         }
6646         # this handles yet another fredforfaen special case where a mounted drive
6647         # has the search string in its name
6648         $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ {
6649                 # note, older df in bsd do not have file system column
6650                 if ( NF == "7" && $(NF - 1) ~ /[0-9]+%/ ) {
6651                         fileSystem=$(NF - 5)
6652                 }
6653                 else {
6654                         fileSystem=""
6655                 }
6656                 print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," fileSystem "," devBase 
6657         }
6658         # skip all these, including the first, header line. Use the --exclude-type
6659         # to handle new filesystems types we do not want listed here
6660         $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ {
6661                 # this is to avoid file systems with spaces in their names, that will make
6662                 # the test show the wrong data in each of the fields, if no x%, then do not use
6663                 # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name
6664                 if ( $(NF - 1) ~ /[0-9]+%/ ) {
6665                         # note, older df in bsd do not have file system column
6666                         if ( NF == "7" ) {
6667                                 fileSystem=$(NF - 5)
6668                         }
6669                         else {
6670                                 fileSystem=""
6671                         }
6672                         print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," fileSystem "," devBase 
6673                 }
6674                 # these two cases construct the space containing name
6675                 else if ( $(NF - 2) ~ /[0-9]+%/ ) {
6676                         # note, older df in bsd do not have file system column
6677                         if ( NF == "8" && $(NF - 6) !~ /^[0-9]+/ ) {
6678                                 fileSystem=$(NF - 6)
6679                         }
6680                         else {
6681                                 fileSystem=""
6682                         }
6683                         print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," fileSystem "," devBase
6684                 }
6685                 else if ( $(NF - 3) ~ /[0-9]+%/ ) {
6686                         # note, older df in bsd do not have file system column
6687                         if ( NF == "9" && $(NF - 7) !~ /^[0-9]+/ ) {
6688                                 fileSystem=$(NF - 7)
6689                         }
6690                         else {
6691                                 fileSystem=""
6692                         }
6693                         print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," fileSystem "," devBase 
6694                 }
6695         }' )
6696         
6697         # now add the swap partition data, don't want to show swap files, just partitions,
6698         # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this
6699         # data, it's the same exact output as swapon -s
6700         $( echo "$swap_data" | gawk -v bsdType=$BSD_TYPE '
6701         BEGIN {
6702                 swapCounter = 1
6703                 usedHolder=""
6704                 sizeHolder=""
6705         }
6706         /^\/dev/ {
6707                 if ( bsdType == "" ) {
6708                         usedHolder=$4
6709                         sizeHolder=$3
6710                 }
6711                 else {
6712                         usedHolder=$3
6713                         sizeHolder=$2
6714                 }
6715                 size = sprintf( "%.2f", sizeHolder*1024/1000**3 )
6716                 devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6717                 used = sprintf( "%.2f", usedHolder*1024/1000**3 )
6718                 percentUsed = sprintf( "%.0f", ( usedHolder/sizeHolder )*100 )
6719                 print "swap-" swapCounter "," size "GB," used "GB," percentUsed "%,main," "swap," devBase
6720                 swapCounter = ++swapCounter
6721         }' ) )
6722         IFS="$ORIGINAL_IFS"
6723         
6724         temp_array=${A_PARTITION_DATA[@]}
6725         # echo $temp_array
6726         log_function_data "1: A_PARTITION_DATA:\n$temp_array"
6727         
6728         # we'll use this for older systems where no filesystem type is shown in df
6729         if [[ $BSD_TYPE == 'bsd' ]];then
6730                 mount_data="$( mount )"
6731         fi
6732         # now we'll handle some fringe cases where irregular df -hT output shows /dev/disk/.. instead of 
6733         # /dev/h|sdxy type data for column 1, . A_PARTITION_DATA[6]
6734         # Here we just search for the uuid/label and then grab the end of the line to get the right dev item.
6735         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6736         do
6737                 IFS=","
6738                 a_partition_working=( ${A_PARTITION_DATA[i]} )
6739                 IFS="$ORIGINAL_IFS"
6740                 
6741                 dev_item=${a_partition_working[6]} # reset each loop
6742                 fs_type=${a_partition_working[5]}
6743                 # older bsds have df minus -T so can't get fs type easily, try using mount instead
6744                 if [[ $BSD_TYPE == 'bsd' && -z $fs_type && -n $dev_item ]];then
6745                         dev_bsd_item=$( sed -e 's/non-dev-//' -e 's|/|\\/|g' <<< "$dev_item" )
6746                         fs_type=$( gawk -F '(' '
6747                         /'$dev_bsd_item'/ {
6748                                 # slice out everything after / plus the first comma
6749                                 sub( /,.*/, "", $2 )
6750                                 print $2
6751                                 exit
6752                         }' <<< "$mount_data" )
6753                 fi
6754                 # note: for swap this will already be set
6755                 if [[ -n $( grep -E '(by-uuid|by-label)' <<< $dev_item ) ]];then
6756                         dev_working_item=$( basename $dev_item )
6757                         if [[ -n $DEV_DISK_UUID ]];then
6758                                 dev_item=$( echo "$DEV_DISK_UUID" | gawk '
6759                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
6760                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6761                                                 print item
6762                                                 exit
6763                                         }' )
6764                         fi
6765                         # if we didn't find anything for uuid try label
6766                         if [[ -z $dev_item && -n $DEV_DISK_LABEL ]];then
6767                                 dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
6768                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
6769                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6770                                                 print item
6771                                                 exit
6772                                         }' )
6773                         fi
6774                 elif [[ -n $( grep 'mapper/' <<< $dev_item ) ]];then
6775                         # get the mapper actual dev item
6776                         dev_item=$( get_dev_processed_item "$dev_item" )
6777                 fi
6778                 
6779                 if [[ -n $dev_item ]];then
6780                         # assemble everything we could get for dev/h/dx, label, and uuid
6781                         IFS=","
6782                         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
6783                         IFS="$ORIGINAL_IFS"
6784                 fi
6785         done
6786         temp_array=${A_PARTITION_DATA[@]}
6787         # echo $temp_array
6788         log_function_data "2: A_PARTITION_DATA:\n$temp_array"
6789         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
6790                 get_partition_data_advanced
6791         fi
6792         eval $LOGFE
6793 }
6794
6795 # first get the locations of the mount points for label/uuid detection
6796 get_partition_data_advanced()
6797 {
6798         eval $LOGFS
6799         local a_partition_working='' dev_partition_data=''
6800         local dev_item='' dev_label='' dev_uuid='' temp_array=''
6801         local mount_point=''
6802         # set dev disk label/mapper/uuid data globals
6803         get_partition_dev_data 'label'
6804         get_partition_dev_data 'mapper'
6805         get_partition_dev_data 'uuid'
6806
6807         if [[ $B_MOUNTS_FILE == 'true' ]];then
6808                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6809                 do
6810                         IFS=","
6811                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6812                         IFS="$ORIGINAL_IFS"
6813                         
6814                         # note: for swap this will already be set
6815                         if [[ -z ${a_partition_working[6]} ]];then
6816                                 
6817                                 mount_point=$( sed 's|/|\\/|g'  <<< ${a_partition_working[0]} )
6818                                 #echo mount_point $mount_point
6819                                 dev_partition_data=$( gawk '
6820                                 BEGIN {
6821                                         IGNORECASE = 1
6822                                         partition = ""
6823                                         partTemp = ""
6824                                 }
6825                                 # trying to handle space in name
6826 #                               gsub( /\\040/, " ", $0 )
6827                                 /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" {
6828                                         # initialize the variables
6829                                         label = ""
6830                                         uuid = ""
6831
6832                                         # slice out the /dev
6833                                         partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6834                                         # label and uuid can occur for root, set partition to null now
6835                                         if ( partition ~ /by-label/ ) {
6836                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 )
6837                                                 partition = ""
6838                                         }
6839                                         if ( partition ~ /by-uuid/ ) {
6840                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 )
6841                                                 partition = ""
6842                                         }
6843
6844                                         # handle /dev/root for / id
6845                                         if ( partition == "root" ) {
6846                                                 # if this works, great, otherwise, just set this to null values
6847                                                 partTemp="'$( readlink /dev/root 2>/dev/null )'"
6848                                                 if ( partTemp != "" ) {
6849                                                         if ( partTemp ~ /[hsv]d[a-z][0-9]{1,2}/ ) {
6850                                                                 partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp )
6851                                                         }
6852                                                         else if ( partTemp ~ /by-uuid/ ) {
6853                                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp )
6854                                                                 partition="" # set null to let real location get discovered
6855                                                         }
6856                                                         else if ( partTemp ~ /by-label/ ) {
6857                                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp )
6858                                                                 partition="" # set null to let real location get discovered
6859                                                         }
6860                                                 }
6861                                                 else {
6862                                                         partition = ""
6863                                                         label = ""
6864                                                         uuid = ""
6865                                                 }
6866                                         }
6867                                         print partition "," label "," uuid
6868                                         exit
6869                                 }'      $FILE_MOUNTS )
6870
6871                                 # assemble everything we could get for dev/h/dx, label, and uuid
6872                                 IFS=","
6873                                 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
6874                                 IFS="$ORIGINAL_IFS"
6875                         fi
6876                         ## now we're ready to proceed filling in the data
6877                         IFS=","
6878                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6879                         IFS="$ORIGINAL_IFS"
6880                         # get the mapper actual dev item first, in case it's mapped
6881                         dev_item=$( get_dev_processed_item "${a_partition_working[6]}" )
6882                         # make sure not to slice off rest if it's a network mounted file system
6883                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
6884                                 dev_item=$( basename $dev_item ) ## needed to avoid error in case name still has / in it
6885                         fi
6886                         dev_label=${a_partition_working[7]}
6887                         dev_uuid=${a_partition_working[8]}
6888                         # then if dev data/uuid is incomplete, try to get missing piece
6889                         # it's more likely we'll get a uuid than a label. But this should get the
6890                         # dev item set no matter what, so then we can get the rest of any missing data
6891                         # first we'll get the dev_item if it's missing
6892                         if [[ -z $dev_item ]];then
6893                                 if [[ -n $DEV_DISK_UUID && -n $dev_uuid ]];then
6894                                         dev_item=$( echo "$DEV_DISK_UUID" | gawk '
6895                                                 $0 ~ /[ \t]'$dev_uuid'[ \t]/ {
6896                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6897                                                         print item
6898                                                         exit
6899                                                 }' )
6900                                 elif [[ -n $DEV_DISK_LABEL && -n $dev_label ]];then
6901                                         dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
6902                                                 # first we need to change space x20 in by-label back to a real space
6903                                                 #gsub( /x20/, " ", $0 )
6904                                                 # then we can see if the string is there
6905                                                 $0 ~ /[ \t]'$dev_label'[ \t]/ {
6906                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6907                                                         print item
6908                                                         exit
6909                                                 }' )
6910                                 fi
6911                         fi
6912                         
6913                         # this can trigger all kinds of weird errors if it is a non /dev path, like: remote:/machine/name
6914                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
6915                                 if [[ -n $DEV_DISK_UUID && -z $dev_uuid ]];then
6916                                         dev_uuid=$( echo "$DEV_DISK_UUID" | gawk  '
6917                                         /'$dev_item'$/ {
6918                                                 print $(NF - 2)
6919                                                 exit
6920                                         }' )
6921                                 fi
6922                                 if [[ -n $DEV_DISK_LABEL && -z $dev_label ]];then
6923                                         dev_label=$( echo "$DEV_DISK_LABEL" | gawk '
6924                                         /'$dev_item'$/ {
6925                                                 print $(NF - 2)
6926                                                 exit
6927                                         }' )
6928                                 fi
6929                         fi
6930
6931                         # assemble everything we could get for dev/h/dx, label, and uuid
6932                         IFS=","
6933                         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
6934                         IFS="$ORIGINAL_IFS"
6935                 done
6936                 log_function_data 'cat' "$FILE_MOUNTS"
6937         else
6938                 if [[ $BSD_TYPE == 'bsd' ]];then
6939                         get_partition_data_advanced_bsd
6940                 fi
6941         fi
6942         temp_array=${A_PARTITION_DATA[@]}
6943         # echo $temp_array
6944         log_function_data "3-advanced: A_PARTITION_DATA:\n$temp_array"
6945         eval $LOGFE
6946 }
6947
6948 get_partition_data_advanced_bsd()
6949 {
6950         eval $LOGFS
6951         local gpart_data="$( gpart list 2>/dev/null )"
6952         local a_partition_working='' label_uuid='' dev_item=''
6953         
6954         if [[ -n $gpart_data ]];then
6955                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6956                 do
6957                         IFS=","
6958                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6959                         IFS="$ORIGINAL_IFS"
6960                         # no need to use the rest of the name if it's not a straight /dev/item
6961                         dev_item=$( basename ${a_partition_working[6]} )
6962                         
6963                         label_uuid=$( gawk -F ':' '
6964                         BEGIN {
6965                                 IGNORECASE=1
6966                                 label=""
6967                                 uuid=""
6968                         }
6969                         /^[0-9]+\.[[:space:]]*Name.*'$dev_item'/ {
6970                                 while ( getline && $1 !~ /^[0-9]+\.[[:space:]]*Name/ ) {
6971                                         if ( $1 ~ /rawuuid/ ) {
6972                                                 gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
6973                                                 uuid=$2
6974                                         }
6975                                         if ( $1 ~ /label/ ) {
6976                                                 gsub(/^[[:space:]]+|[[:space:]]+$|none|\(null\)/,"",$2)
6977                                                 label=$2
6978                                         }
6979                                 }
6980                                 print label","uuid
6981                                 exit
6982                         }' <<< "$gpart_data" )
6983
6984                         # assemble everything we could get for dev/h/dx, label, and uuid
6985                         IFS=","
6986                         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
6987                         IFS="$ORIGINAL_IFS"
6988                 done
6989         fi
6990         eval $LOGFE
6991 }
6992
6993 # args: $1 - uuid/label/id/mapper
6994 get_partition_dev_data()
6995 {
6996         eval $LOGFS
6997         
6998         # only run these tests once per directory to avoid excessive queries to fs
6999         case $1 in
7000                 id)
7001                         if [[ $B_ID_SET != 'true' ]];then
7002                                 if [[ -d /dev/disk/by-id ]];then
7003                                         DEV_DISK_ID="$( ls -l /dev/disk/by-id )"
7004                                 fi
7005                                 B_ID_SET='true'
7006                         fi
7007                         ;;
7008                 label)
7009                         if [[ $B_LABEL_SET != 'true' ]];then
7010                                 if [[ -d /dev/disk/by-label ]];then
7011                                         DEV_DISK_LABEL="$( ls -l /dev/disk/by-label )"
7012                                 fi
7013                                 B_LABEL_SET='true'
7014                         fi
7015                         ;;
7016                 mapper)
7017                         if [[ $B_MAPPER_SET != 'true' ]];then
7018                                 if [[ -d /dev/mapper ]];then
7019                                         DEV_DISK_MAPPER="$( ls -l /dev/mapper )"
7020                                 fi
7021                                 B_MAPPER_SET='true'
7022                         fi
7023                         ;;
7024                 uuid)
7025                         if [[ $B_UUID_SET != 'true' ]];then
7026                                 if [[ -d /dev/disk/by-uuid ]];then
7027                                         DEV_DISK_UUID="$( ls -l /dev/disk/by-uuid )"
7028                                 fi
7029                                 B_UUID_SET='true'
7030                         fi
7031                         ;;
7032                 
7033         esac
7034         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"
7035         # debugging section, uncomment to insert user data
7036 #       DEV_DISK_LABEL='
7037 #
7038 # '
7039 # DEV_DISK_UUID='
7040 #
7041 # '
7042 # DEV_DISK_MAPPER='
7043 #
7044 # '
7045         eval $LOGFE
7046 }
7047
7048 # args: $1 - dev item, check for mapper, then get actual dev item if mapped
7049 # eg: lrwxrwxrwx 1 root root       7 Sep 26 15:10 truecrypt1 -> ../dm-2 
7050 get_dev_processed_item()
7051 {
7052         eval $LOGFS
7053         
7054         local dev_item=$1 dev_return=''
7055         
7056         if [[ -n $DEV_DISK_MAPPER && -n $( grep -is 'mapper/' <<< $dev_item ) ]];then
7057                 dev_return=$( echo "$DEV_DISK_MAPPER" | gawk '
7058                 $( NF - 2 ) ~ /^'$( basename $dev_item )'$/ {
7059                         item=gensub( /..\/(.+)/, "\\1", 1, $NF )
7060                         print item
7061                 }' )
7062         fi
7063         if [[ -z $dev_return ]];then
7064                 dev_return=$dev_item
7065         fi
7066         
7067         echo $dev_return
7068
7069         eval $LOGFE
7070 }
7071
7072 get_patch_version_string()
7073 {
7074         local patch_version_number=$( sed 's/^[0]*//' <<< $SCRIPT_PATCH_NUMBER )
7075         
7076         if [[ -n $patch_version_number ]];then
7077                 patch_version_number="-$patch_version_number"
7078                 # for cases where it was for example: 00-bsd cleaned to --bsd trim out one -
7079                 if [[ -n $( grep '\--' <<< $patch_version_number ) ]];then
7080                         patch_version_number=$( sed 's/--/-/' <<< $patch_version_number )
7081                 fi
7082         fi
7083         echo $patch_version_number
7084 }
7085
7086 get_pciconf_data()
7087 {
7088         eval $LOGFS
7089         
7090         local pciconf_data='' temp_array=''
7091         
7092         if [[ $B_PCICONF == 'true' ]];then
7093                 pciconf_data="$( pciconf -lv 2>/dev/null )"
7094                 if [[ -n $pciconf_data ]];then
7095                         pciconf_data=$( gawk '
7096                         BEGIN {
7097                                 IGNORECASE=1
7098                         }
7099                         {
7100                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
7101                                         gsub(/[[:space:]]+=[[:space:]]+/, "=",$0)
7102                                         gsub(/^[[:space:]]+|'"'"'|\"|,/, "", $0)
7103                                         gsub(/=0x/,"=",$0)
7104                                         # line=gensub(/.*[[:space:]]+(class=[^[:space:]]*|card=[^[:space:]]*)|chip=[^[:space:]]*|rev=[^[:space:]]*|hdr=[^[:space:]]*).*/,"\n\\1","g",$0)
7105                                         line=gensub(/(.*@.*)/,"\n\\1",$0)
7106                                         print line
7107                         }' <<< "$pciconf_data" )
7108                         # create empty last line with this spacing trick
7109                         pciconf_data="$pciconf_data
7110
7111 EOF"
7112                         # echo "$pciconf_data"
7113                         # now insert into arrays
7114                         IFS=$'\n'
7115                         A_PCICONF_DATA=( $( gawk '
7116                         BEGIN {
7117                                 fullLine=""
7118                                 driver=""
7119                                 vendor=""
7120                                 device=""
7121                                 class=""
7122                                 chipId=""
7123                                 pciId=""
7124                                 itemData=""
7125                                 IGNORECASE=1
7126                         }
7127                         /^.*@/ {
7128                                 pciId=""
7129                                 vendor=""
7130                                 class=""
7131                                 driver=""
7132                                 device=""
7133                                 chipId=""
7134                                 itemData=$1
7135                                 
7136                                 driver=gensub(/^([^@]+)@.*/, "\\1", itemData )
7137                                 pciId=gensub(/^.*@pci([0-9\.:]+).*/, "\\1", itemData )
7138                                 sub(/:$/, "", pciId)
7139                                 itemData=$4
7140                                 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 )
7141                                 if ( $2 == "class=020000" ) {
7142                                         class="network"
7143                                 }
7144                                 else if ( $2 == "class=030000" ) {
7145                                         class="display"
7146                                 }
7147                                 else if ( $2 == "class=040300" ) {
7148                                         class="audio"
7149                                 }
7150                                 
7151                                 while ( getline && $1 !~ /^$/ ) {
7152                                         if ( $1 ~ /^vendor/ ) {
7153                                                 sub(/^vendor=/, "", $1 )
7154                                                 vendor=$0
7155                                         }
7156                                         else if ( $1 ~ /^device/ ) {
7157                                                 sub(/^device=/, "", $1 )
7158                                                 device=$0
7159                                         }
7160                                         else if ( $1 ~ /^class=/ && class == "" ) {
7161                                                 sub(/^class=/, "", $1)
7162                                                 class=$0
7163                                         }
7164                                 }
7165                                 if ( device == "" ) {
7166                                         device=vendor
7167                                 }
7168                                 
7169                                 fullLine=class "," device "," vendor "," driver "," pciId "," chipId
7170                                 print fullLine
7171                         
7172                         }' <<< "$pciconf_data" ))
7173                         IFS="$ORIGINAL_IFS"
7174                 fi
7175         else
7176                 A_PCICONF_DATA='pciconf-not-installed'
7177         fi
7178         B_PCICONF_SET='true'
7179         temp_array=${A_PCICONF_DATA[@]}
7180         log_function_data "$temp_array"
7181         log_function_data "$pciconf_data"
7182         eval $LOGFE
7183 }
7184
7185 # packs standard card arrays using the pciconf stuff
7186 # args: $1 - audio/network/display - matches first item in A_PCICONF_DATA arrays
7187 get_pciconf_card_data()
7188 {
7189         eval $LOGFS
7190         local a_temp='' array_string='' j=0 device_string=''
7191         local ip_tool_command=$( type -p ifconfig )
7192         local mac='' state='' speed='' duplex='' network_string=''
7193         
7194         for (( i=0;i<${#A_PCICONF_DATA[@]};i++ ))
7195         do
7196                 IFS=','
7197                 a_temp=( ${A_PCICONF_DATA[i]} )
7198                 IFS="$ORIGINAL_IFS"
7199                 
7200                 if [[ ${a_temp[0]} == $1 ]];then
7201                         # don't print the vendor if it's already in the device name
7202                         if [[ -z $( grep -i "${a_temp[2]}" <<< "${a_temp[1]}" ) ]];then
7203                                 device_string="${a_temp[2]} ${a_temp[1]}"
7204                         else
7205                                 device_string=${a_temp[1]}
7206                         fi
7207                         case $1 in
7208                                 audio)
7209                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},,${a_temp[5]}"
7210                                         A_AUDIO_DATA[j]=$array_string
7211                                         ;;
7212                                 display)
7213                                         array_string="$device_string,${a_temp[4]},${a_temp[5]}"
7214                                         A_GRAPHICS_CARD_DATA[j]=$array_string
7215                                         ;;
7216                                 network)
7217                                         if [[ -n $ip_tool_command && -n ${a_temp[3]} ]];then
7218                                                 network_string=$(       $ip_tool_command ${a_temp[3]} | gawk '
7219                                                 BEGIN {
7220                                                         IGNORECASE=1
7221                                                         mac=""
7222                                                         state=""
7223                                                         speed=""
7224                                                         duplex=""
7225                                                 }
7226                                                 /^[[:space:]]*ether/ {
7227                                                         mac = $2
7228                                                 }
7229                                                 /^[[:space:]]*media/ {
7230                                                         if ( $0 ~ /<.*>/ ) {
7231                                                                 duplex=gensub(/.*<([^>]+)>.*/,"\\1",$0)
7232                                                         }
7233                                                         if ( $0 ~ /\(.*\)/ ) {
7234                                                                 speed=gensub(/.*\(([^<[:space:]]+).*\).*/,"\\1",$0)
7235                                                         }
7236                                                 }
7237                                                 /^[[:space:]]*status/ {
7238                                                         sub(/.*status[:]?[[:space:]]*/,"", $0)
7239                                                         state=$0
7240                                                 }
7241                                                 END {
7242                                                         print state "~" speed "~" mac "~" duplex
7243                                                 }')
7244                                         fi
7245                                         if [[ -n $network_string ]];then
7246                                                 mac=$( cut -d '~' -f 3 <<< $network_string )
7247                                                 state=$( cut -d '~' -f 1 <<< $network_string )
7248                                                 speed=$( cut -d '~' -f 2 <<< $network_string )
7249                                                 duplex=$( cut -d '~' -f 4 <<< $network_string )
7250                                         fi
7251                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},${a_temp[3]},$state,$speed,$duplex,$mac,${a_temp[5]}"
7252                                         A_NETWORK_DATA[j]=$array_string
7253                                         ;;
7254                         esac
7255                         ((j++))
7256                 fi
7257         done
7258         
7259         eval $LOGFE
7260 }
7261
7262 # args: $1 - type cpu/mem 
7263 get_ps_tcm_data()
7264 {
7265         eval $LOGFS
7266         local array_length='' reorder_temp='' i=0 head_tail='' sort_type='' ps_data=''
7267         
7268         # bummer, have to make it more complex here because of reverse sort
7269         # orders in output, pesky lack of support of +rss in old systems
7270         case $1 in
7271                 mem)
7272                         if [[ $BSD_TYPE != 'bsd' ]];then
7273                                 sort_type='ps aux --sort -rss'
7274                                 head_tail='head'
7275                         else
7276                                 sort_type='ps aux -m'
7277                                 head_tail='head'
7278                         fi
7279                         ;;
7280                 cpu)
7281                         if [[ $BSD_TYPE != 'bsd' ]];then
7282                                 sort_type='ps aux --sort %cpu'
7283                                 head_tail='tail'
7284                         else
7285                                 sort_type='ps aux -r'
7286                                 head_tail='head'
7287                         fi
7288                         ;;
7289         esac
7290         
7291         # throttle potential irc abuse
7292         if [[ $B_RUNNING_IN_SHELL != 'true' && $PS_COUNT -gt 5 ]];then
7293                 PS_THROTTLED=$PS_COUNT
7294                 PS_COUNT=5
7295         fi
7296         # use eval here to avoid glitches with -
7297         ps_data="$( eval $sort_type )"
7298
7299         IFS=$'\n'
7300         # note that inxi can use a lot of cpu, and can actually show up here as the script runs
7301         A_PS_DATA=( $( echo "$ps_data" | grep -Ev "($SCRIPT_NAME|%CPU|[[:space:]]ps[[:space:]])" | $head_tail -n $PS_COUNT | gawk '
7302         BEGIN {
7303                 IGNORECASE=1
7304                 appName=""
7305                 appPath=""
7306                 appStarterName=""
7307                 appStarterPath=""
7308                 cpu=""
7309                 mem=""
7310                 pid=""
7311                 user=""
7312                 rss=""
7313         }
7314         {
7315                 cpu=$3
7316                 mem=$4
7317                 pid=$2
7318                 user=$1
7319                 rss=sprintf( "%.2f", $6/1024 )
7320                 # have to get rid of [,],(,) eg: [lockd] which break the printout function compare in bash
7321                 gsub(/\[|\]|\(|\)/,"~", $0 )
7322                 if ( $12 ~ /^\// ){
7323                         appStarterPath=$11
7324                         appPath=$12
7325                 }
7326                 else {
7327                         appStarterPath=$11
7328                         appPath=$11
7329                 }
7330                 appStarterName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appStarterPath )
7331                 appName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appPath )
7332                 print appName "," appPath "," appStarterName "," appStarterPath "," cpu "," mem "," pid "," rss "," user
7333         }
7334         ' ) )
7335         # make the array ordered highest to lowest so output looks the way we expect it to
7336         # this isn't necessary for -rss, and we can't make %cpu ordered the other way, so
7337         # need to reverse it here. -rss is used because on older systems +rss is not supported
7338         if [[ $1 == 'cpu' && $BSD_TYPE != 'bsd' ]];then
7339                 array_length=${#A_PS_DATA[@]}; 
7340                 while (( $i < $array_length/2 ))
7341                 do 
7342                         reorder_temp=${A_PS_DATA[i]}f
7343                         A_PS_DATA[i]=${A_PS_DATA[$array_length-$i-1]}
7344                         A_PS_DATA[$array_length-$i-1]=$reorder_temp
7345                         (( i++ ))
7346                 done 
7347         fi
7348
7349         IFS="$ORIGINAL_IFS"
7350         
7351 #       echo ${A_PS_DATA[@]}
7352         eval $LOGFE
7353 }
7354
7355 # mdstat syntax information: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
7356 # note that this does NOT use either Disk or Partition information for now, ie, there
7357 # is no connection between the data types, but the output should still be consistent
7358 get_raid_data()
7359 {
7360         eval $LOGFS
7361         
7362         local mdstat=''
7363                 
7364         if [[ $B_MDSTAT_FILE == 'true' ]];then
7365                 mdstat="$( cat $FILE_MDSTAT 2>/dev/null )"
7366         fi
7367         
7368         if [[ -n $mdstat ]];then
7369                 # need to make sure there's always a newline in front of each record type, and
7370                 # also correct possible weird formats for the output from older kernels etc.
7371                 mdstat="$( sed -e 's/^md/\nmd/' -e 's/^unused[[:space:]]/\nunused /' \
7372                 -e 's/read_ahead/\nread_ahead/' -e 's/^resync=/\nresync=/' -e 's/^Event/\nEvent/' \
7373                 -e 's/^[[:space:]]*$//' -e 's/[[:space:]]read_ahead/\nread_ahead/' <<< "$mdstat" )"
7374                 # some fringe cases do not end as expected, so need to add newlines plus EOF to make sure while loop doesn't spin
7375                 mdstat=$( echo -e "$mdstat\n\nEOF" )
7376
7377                 IFS=$'\n'
7378                 A_RAID_DATA=( $(
7379                 gawk '
7380                 BEGIN {
7381                         IGNORECASE=1
7382                         RS="\n"
7383                 }
7384                 
7385                 /^personalities/ {
7386                         KernelRaidSupport = gensub(/personalities[[:space:]]*:[[:space:]]*(.*)/, "\\1", 1, $0)
7387                         # clean off the brackets
7388                         gsub(/[\[\]]/,"",KernelRaidSupport)
7389                         print "KernelRaidSupport," KernelRaidSupport
7390                 }
7391                 /^read_ahead/ {
7392                         ReadAhead=gensub(/read_ahead (.*)/, "\\1", 1 )
7393                         print "ReadAhead," ReadAhead
7394                 }
7395                 /^Event:/ {
7396                         print "raidEvent," $NF
7397                 }
7398                 # print logic will search for this value and use it to print out the unused devices data
7399                 /^unused devices/ {
7400                         unusedDevices = gensub(/^unused devices:[[:space:]][<]?([^>]*)[>]?.*/, "\\1", 1, $0)
7401                         print "UnusedDevices," unusedDevices
7402                 }
7403                 
7404                 /^md/ {
7405                         # reset for each record loop through
7406                         deviceState = ""
7407                         bitmapValues = ""
7408                         blocks = ""
7409                         chunkSize = ""
7410                         components = ""
7411                         device = ""
7412                         deviceReport = ""
7413                         finishTime = ""
7414                         recoverSpeed = ""
7415                         recoveryProgressBar = ""
7416                         recoveryPercent = ""
7417                         raidLevel = ""
7418                         sectorsRecovered = ""
7419                         separator = ""
7420                         superBlock = ""
7421                         uData = ""
7422                         
7423                         while ( !/^[[:space:]]*$/  ) {
7424                                 gsub(/,/, " ", $0 )
7425                                 gsub(/[[:space:]]+/, " ", $0 )
7426                                 if ( $0 ~ /^md/ ) {
7427                                         device = gensub(/(md.*)[[:space:]]?:/, "\\1", "1", $1 )
7428                                 }
7429                                 if ( $0 ~ /mirror|raid[0-9]+/ ) {
7430                                         raidLevel = gensub(/(.*)raid([0-9]+)(.*)/, "\\2", "g", $0 )
7431                                 }
7432                                 if ( $0 ~ /(active \(auto-read-only\)|active|inactive)/ ) {
7433                                         deviceState = gensub(/(.*) (active \(auto-read-only\)|active|inactive) (.*)/, "\\2", "1", $0 )
7434                                 }
7435                                 # gawk will not return all the components using gensub, only last one
7436                                 separator = ""
7437                                 for ( i=3; i<=NF; i++ ) {
7438                                         if ( $i ~ /[hs]d[a-z][0-9]*(\[[0-9]+\])?(\([SF]\))?/ ) {
7439                                                 components = components separator $i
7440                                                 separator=" "
7441                                         }
7442                                 }
7443                                 if ( $0 ~ /blocks/ ) {
7444                                         blocks = gensub(/(.*[[:space:]]+)?([0-9]+)[[:space:]]blocks.*/, "\\2", "1", $0)
7445                                 }
7446                                 if ( $0 ~ /super[[:space:]][0-9\.]+/ ) {
7447                                         superBlock = gensub(/.*[[:space:]]super[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
7448                                 }
7449                                 if ( $0 ~ /algorithm[[:space:]][0-9\.]+/ ) {
7450                                         algorithm = gensub(/.*[[:space:]]algorithm[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
7451                                 }
7452                                 if ( $0 ~ /\[[0-9]+\/[0-9]+\]/ ) {
7453                                         deviceReport = gensub(/.*[[:space:]]\[([0-9]+\/[0-9]+)\][[:space:]].*/, "\\1", "1", $0)
7454                                         uData = gensub(/.*[[:space:]]\[([U_]+)\]/, "\\1", "1", $0)
7455                                 }
7456                                 # need to avoid this:  bitmap: 0/10 pages [0KB], 16384KB chunk
7457                                 # while currently all the normal chunks are marked with k, not kb, this can change in the future
7458                                 if ( $0 ~ /[0-9]+[k] chunk/ && $0 !~ /bitmap/ ) {
7459                                         chunkSize = gensub(/(.*) ([0-9]+[k]) chunk.*/, "\\2", "1", $0)
7460                                 }
7461                                 if ( $0 ~ /^resync=/ ) {
7462                                         sub(/resync=/,"")
7463                                         print "resyncStatus," $0
7464                                 }
7465                                 if ( $0 ~ /\[[=]*>[\.]*\].*(resync|recovery)/ ) {
7466                                         recoveryProgressBar = gensub(/.*(\[[=]*>[\.]*\]).*/, "\\1",1,$0)
7467                                 }
7468                                 if ( $0 ~ / (resync|recovery)[[:space:]]*=/ ) {
7469                                         recoveryPercent = gensub(/.* (resync|recovery)[[:space:]]*=[[:space:]]*([0-9\.]+%).*/, "\\1~\\2", 1 )
7470                                         if ( $0 ~ /[[:space:]]\([0-9]+\/[0-9]+\)/ ) {
7471                                                 sectorsRecovered = gensub(/.* \(([0-9]+\/[0-9]+)\).*/, "\\1", 1, $0 )
7472                                         }
7473                                         if ( $0 ~ /finish[[:space:]]*=/ ) {
7474                                                 finishTime = gensub(/.* finish[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+) .*/, "\\1 \\2", 1, $0 )
7475                                         }
7476                                         if ( $0 ~ /speed[[:space:]]*=/ ) {
7477                                                 recoverSpeed = gensub(/.* speed[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+\/[a-z]+)/, "\\1 \\2", 1, $0 )
7478                                         }
7479                                 }
7480                                 if ( $0 ~ /bitmap/ ) {
7481                                         bitmapValues = gensub(/(.*[[:space:]])?bitmap:(.*)/, "\\2", 1, $0 )
7482                                 }
7483                                 
7484                                 getline
7485                         }
7486                         raidString = device "," deviceState "," raidLevel "," components "," deviceReport "," uData 
7487                         raidString = raidString "," blocks "," superBlock "," algorithm "," chunkSize "," bitmapValues
7488                         raidString = raidString "," recoveryProgressBar "," recoveryPercent "," sectorsRecovered "," finishTime "," recoverSpeed
7489                         
7490                         print raidString
7491                 }
7492                 ' <<< "$mdstat" ) )
7493                 IFS="$ORIGINAL_IFS"
7494         else
7495                 if [[ $BSD_TYPE == 'bsd' ]];then
7496                         get_raid_data_bsd
7497                 fi
7498         fi
7499         B_RAID_SET='true'
7500         temp_array=${A_RAID_DATA[@]}
7501         log_function_data "A_RAID_DATA: $temp_array"
7502 #       echo -e "A_RAID_DATA:\n${temp_array}"
7503         
7504         eval $LOGFE
7505 }
7506
7507 get_raid_data_bsd()
7508 {
7509         eval $LOGFS
7510         local zpool_path=$( type -p zpool 2>/dev/null )
7511         local zpool_data=''
7512         
7513         if [[ -n $zpool_path ]];then
7514                 B_BSD_RAID='true'
7515                 # bsd sed does not support inserting a true \n so use this trick
7516                 zpool_data="$( $zpool_path list -v | sed $SED_RX 's/^([^[:space:]])/\
7517 \1/' )"
7518 #               echo "$zpool_data"
7519                 IFS=$'\n'
7520                 A_RAID_DATA=( $(
7521                 gawk '
7522                 BEGIN {
7523                         raidString=""
7524                         separator=""
7525                         components=""
7526                         reportSize=""
7527                         blocksAvailable=""
7528                         chunkRaidAllocated=""
7529                 }
7530                 /SIZE.*ALLOC/ {
7531                         sub(/.*ALLOC.*/,"", $0)
7532                 }
7533                 /^[^[:space:]]/ {
7534                         components=""
7535                         separator=""
7536                         raidLevel=""
7537                         device=$1
7538                         deviceState=$7
7539                         reportSize=$2
7540                         blocksAvailable=$4
7541                         chunkRaidAllocated=$3
7542                         
7543                         # go to the next line now, this will probably need fixing later with weird data sets
7544                         getline
7545                         if ( $1 != "" ) {
7546                                 raidLevel="zfs " $1
7547                         }
7548                         
7549                         while ( getline && $1 !~ /^$/ ) {
7550                                 # print $1
7551                                 components = components separator $1
7552                                 separator=" "
7553                         }
7554
7555                         # print $1
7556                         raidString = device "," deviceState "," raidLevel "," components "," reportSize "," uData 
7557                         raidString = raidString "," blocksAvailable "," superBlock "," algorithm "," chunkRaidAllocated 
7558                         # none of these are used currently
7559                         raidString = raidString "," bitmapValues  "," recoveryProgressBar "," recoveryPercent 
7560                         raidString = raidString "," sectorsRecovered "," finishTime "," recoverSpeed
7561                         gsub(/~/,"",raidString)
7562                         print raidString
7563                 }' <<< "$zpool_data" ) )
7564                 IFS="$ORIGINAL_IFS"
7565                 get_raid_component_data_bsd
7566         fi
7567         eval $LOGFE
7568 }
7569
7570 # note, we've already tested for zpool so no further tests required
7571 get_raid_component_data_bsd()
7572 {
7573         eval $LOGFS
7574         local a_raid_data='' array_string='' component='' component_string='' 
7575         local zpool_status='' device='' separator='' component_status=''
7576         
7577         for (( i=0; i<${#A_RAID_DATA[@]}; i++))
7578         do
7579                 IFS=","
7580                 a_raid_data=( ${A_RAID_DATA[i]} )
7581                 IFS="$ORIGINAL_IFS"
7582                 separator=''
7583                 component_string=''
7584                 component_status=''
7585                 zpool_status=''
7586                 device=${a_raid_data[0]}
7587                 zpool_status="$( zpool status $device )"
7588                 # we will remove ONLINE for status and only use OFFLINE/DEGRADED as tests
7589                 # for print output display of issues with components
7590                 for component in ${a_raid_data[3]}
7591                 do
7592                         component_status=$( gawk '
7593                         BEGIN {
7594                                 IGNORECASE=1
7595                         }
7596                         $1 ~ /^'$component'$/ {
7597                                 sub( /ONLINE/, "", $2 )
7598                                 print "'$component'" $2
7599                                 exit
7600                         }' <<< "$zpool_status" )
7601                         component_string="$component_string$separator$component_status"
7602                         separator=' '
7603                 done
7604                 array_string="$device,${a_raid_data[1]},${a_raid_data[2]},$component_string,${a_raid_data[4]}"
7605                 array_string="$array_string,${a_raid_data[5]},${a_raid_data[6]},${a_raid_data[7]},${a_raid_data[8]}"
7606                 array_string="$array_string,${a_raid_data[9]},${a_raid_data[10]},${a_raid_data[11]},${a_raid_data[12]},"
7607                 array_string="$array_string${a_raid_data[13]},${a_raid_data[14]},${a_raid_data[15]}"
7608                 IFS=","
7609                 A_RAID_DATA[i]=$array_string
7610                 IFS="$ORIGINAL_IFS"
7611         done
7612         
7613         eval $LOGFE
7614 }
7615 # get_raid_data_bsd;exit
7616
7617 # Repos will be added as we get distro package manager data to create the repo data. 
7618 # This method will output the file name also, which is useful to create output that's 
7619 # neat and readable. Each line of the total number contains the following sections,
7620 # separated by a : for splitting in the print function
7621 # part one, repo type/string : part two, file name, if present, of info : part 3, repo data
7622 get_repo_data()
7623 {
7624         eval $LOGFS
7625         local repo_file='' repo_data_working='' repo_data_working2='' repo_line='' repo_files=''
7626         local repo_name=''
7627         local apt_file='/etc/apt/sources.list' yum_repo_dir='/etc/yum.repos.d/' yum_conf='/etc/yum.conf'
7628         local pacman_conf='/etc/pacman.conf' pacman_repo_dir='/etc/pacman.d/' pisi_dir='/etc/pisi/'
7629         local zypp_repo_dir='/etc/zypp/repos.d/' freebsd_conf='/etc/portsnap.conf'
7630         
7631         # apt - debian, buntus, also sometimes some yum/rpm repos may create apt repos here as well
7632         if [[ -f $apt_file || -d $apt_file.d ]];then
7633                 REPO_DATA="$( grep -Esv '(^[[:space:]]*$|^[[:space:]]*#)' $apt_file $apt_file.d/*.list | sed $SED_RX 's/^(.*)/apt sources:\1/' )"
7634         fi
7635         # yum - fedora, redhat, centos, etc. Note that rpmforge also may create apt sources
7636         # in /etc/apt/sources.list.d/. Therefore rather than trying to assume what package manager is
7637         # actually running, inxi will merely note the existence of each repo type for apt/yum. 
7638         # Also, in rpm, you can install apt-rpm for the apt-get command, so it's not good to check for
7639         # only the commands in terms of selecting which repos to show.
7640         if [[ -d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir ]];then
7641                 if [[ -d $yum_repo_dir || -f $yum_conf ]];then
7642                         # older redhats put their yum data in /etc/yum.conf
7643                         repo_files=$( ls $yum_repo_dir*.repo $yum_conf 2>/dev/null )
7644                         repo_name='yum'
7645                 elif [[ -d $zypp_repo_dir ]];then
7646                         repo_files=$( ls $zypp_repo_dir*.repo 2>/dev/null )
7647                         repo_name='zypp'
7648                 fi
7649                 if [[ -n $repo_files ]];then
7650                         for repo_file in $repo_files
7651                         do
7652                                 repo_data_working="$( gawk -v repoFile=$repo_file '
7653                                 # construct the string for the print function to work with, file name: data
7654                                 function print_line( fileName, repoId, repoUrl ){
7655                                         print "'$repo_name' sources:" fileName ":" repoId repoUrl
7656                                 }
7657                                 BEGIN {
7658                                         FS="\n"
7659                                         IGNORECASE=1
7660                                         enabledStatus=""
7661                                         repoTitle=""
7662                                         urlData=""
7663                                 }
7664                                 # this is a hack, assuming that each item has these fields listed, we collect the 3
7665                                 # items one by one, then when the url/enabled fields are set, we print it out and
7666                                 # reset the data. Not elegant but it works. Note that if enabled was not present
7667                                 # we assume it is enabled then, and print the line, reset the variables. This will
7668                                 # miss the last item, so it is printed if found in END
7669                                 /^\[.+\]/ {
7670                                         if ( urlData != "" && repoTitle != "" ){
7671                                                 print_line( repoFile, repoTitle, urlData )
7672                                                 enabledStatus=""
7673                                                 urlData=""
7674                                                 repoTitle=""
7675                                         }
7676                                         gsub( /\[|\]/, "", $1 ) # strip out the brackets
7677                                         repoTitle = $1 " ~ "
7678                                 }
7679                                 /^(mirrorlist|baseurl)/ {
7680                                         sub( /(mirrorlist|baseurl)[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
7681                                         urlData = $1
7682                                 }
7683                                 # note: enabled = 1. enabled = 0 means disabled
7684                                 /^enabled[[:space:]]*=/ {
7685                                         enabledStatus = $1
7686                                 }
7687                                 # print out the line if all 3 values are found, otherwise if a new
7688                                 # repoTitle is hit above, it will print out the line there instead
7689                                 { 
7690                                         if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
7691                                                 if ( enabledStatus !~ /enabled[[:space:]]*=[[:space:]]*0/ ){
7692                                                         print_line( repoFile, repoTitle, urlData )
7693                                                 }
7694                                                 enabledStatus=""
7695                                                 urlData=""
7696                                                 repoTitle=""
7697                                         }
7698                                 }
7699                                 END {
7700                                         # print the last one if there is data for it
7701                                         if ( urlData != ""  && repoTitle != "" ){
7702                                                 print_line( repoFile, repoTitle, urlData )
7703                                         }
7704                                 }
7705                                 ' $repo_file )"
7706                                 
7707                                 # then load the global for each file as it gets filled
7708                                 if [[ -n $repo_data_working ]];then
7709                                         if [[ -z $REPO_DATA ]];then
7710                                                 REPO_DATA="$repo_data_working"
7711                                         else
7712                                                 REPO_DATA="$REPO_DATA
7713 $repo_data_working"
7714                                         fi
7715                                         repo_data_working=''
7716                                 fi
7717                         done
7718                 fi
7719         # pacman - archlinux, going to assume that pisi and arch/pacman, etc don't have the above issue with apt/yum
7720         elif [[ -f $pacman_conf ]];then
7721                 # get list of mirror include files, trim white space off ends
7722                 repo_data_working="$( gawk '
7723                 BEGIN {
7724                         FS="="
7725                         IGNORECASE=1
7726                 }
7727                 /^[[:space:]]*Include/ {
7728                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
7729                         print $2
7730                 }
7731                 ' $pacman_conf )"
7732                 # sort into unique paths only, to be used to search for server = data
7733                 repo_data_working=$( sort -bu <<< "$repo_data_working" | uniq ) 
7734                 repo_data_working="$repo_data_working $pacman_conf"
7735                 for repo_file in $repo_data_working 
7736                 do
7737                         if [[ -f $repo_file ]];then
7738                                 # inserting a new line after each found / processed match
7739                                 repo_data_working2="$repo_data_working2$( gawk -v repoFile=$repo_file '
7740                                 BEGIN {
7741                                         FS="="
7742                                         IGNORECASE=1
7743                                 }
7744                                 /^[[:space:]]*Server/ {
7745                                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
7746                                         print "pacman repo servers:" repoFile ":" $2 "\\n"
7747                                 }
7748                                 ' $repo_file )"
7749                         else
7750                                 echo "Error: file listed in $pacman_conf does not exist - $repo_file"
7751                         fi
7752                 done
7753                 # execute line breaks
7754                 REPO_DATA="$( echo -e $repo_data_working2 )"
7755         # pisi - pardus
7756         elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
7757                 REPO_DATA="$( pisi list-repo )"
7758                 # now we need to create the structure: repo info: repo path
7759                 # we do that by looping through the lines of the output and then
7760                 # putting it back into the <data>:<url> format print repos expects to see
7761                 # note this structure in the data, so store first line and make start of line
7762                 # then when it's an http line, add it, and create the full line collection.
7763 # Pardus-2009.1 [Aktiv]
7764 #       http://packages.pardus.org.tr/pardus-2009.1/pisi-index.xml.bz2
7765 # Contrib [Aktiv]
7766 #       http://packages.pardus.org.tr/contrib-2009/pisi-index.xml.bz2
7767                 while read repo_line
7768                 do
7769                         repo_line=$( gawk '
7770                         {
7771                                 # need to dump leading/trailing spaces and clear out color codes for irc output
7772                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
7773 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
7774                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
7775                                 print $0
7776                         }' <<< $repo_line )
7777                         if [[ -n $( grep '://' <<< $repo_line ) ]];then
7778                                 repo_data_working="$repo_data_working:$repo_line\n"
7779                         else
7780                                 repo_data_working="${repo_data_working}pisi repo:$repo_line"
7781                         fi
7782                 done <<< "$REPO_DATA"
7783                 # echo and execute the line breaks inserted
7784                 REPO_DATA="$( echo -e $repo_data_working )"
7785         # Mandriva/Mageia using: urpmq
7786         elif [[ -n $( type -p urpmq ) ]];then
7787                 REPO_DATA="$( urpmq --list-media active --list-url )"
7788                 # now we need to create the structure: repo info: repo path
7789                 # we do that by looping through the lines of the output and then
7790                 # putting it back into the <data>:<url> format print repos expects to see
7791                 # note this structure in the data, so store first line and make start of line
7792                 # then when it's an http line, add it, and create the full line collection.
7793 # Contrib ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/release
7794 # Contrib Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/updates
7795 # Non-free ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/release
7796 # Non-free Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/updates
7797 # Nonfree Updates (Local19) /mnt/data/mirrors/mageia/distrib/cauldron/x86_64/media/nonfree/updates
7798                 while read repo_line
7799                 do
7800                         repo_line=$( gawk '
7801                         {
7802                                 # need to dump leading/trailing spaces and clear out color codes for irc output
7803                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
7804 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
7805                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
7806                                 print $0
7807                         }' <<< $repo_line )
7808                         # urpmq output is the same each line, repo name space repo url, can be:
7809                         # rsync://, ftp://, file://, http:// OR repo is locally mounted on FS in some cases
7810                         if [[ -n $( grep -E '(://|[[:space:]]/)' <<< $repo_line ) ]];then
7811                                 # cut out the repo first
7812                                 repo_data_working2=$( grep -Eo '([^[:space:]]+://|[[:space:]]/).*' <<< $repo_line )
7813                                 # then get the repo name string by slicing out the url string
7814                                 repo_name=$( sed "s|[[:space:]]*$repo_data_working2||" <<< $repo_line )
7815                                 repo_data_working="${repo_data_working}urpmq repo:$repo_name:$repo_data_working2\n"
7816                         fi
7817                 done <<< "$REPO_DATA"
7818                 # echo and execute the line breaks inserted
7819                 REPO_DATA="$( echo -e $repo_data_working )"
7820         elif [[ -f $freebsd_conf ]];then
7821                 REPO_DATA="$( gawk -F '=' -v repoFile=$freebsd_conf '
7822                 BEGIN {
7823                         IGNORECASE=1
7824                 }
7825                 /^SERVERNAME/ {
7826                         print "BSD ports servers:" repoFile ":" $2
7827                 }
7828                 ' $freebsd_conf )"
7829         fi
7830         eval $LOGFE
7831 }
7832
7833 get_runlevel_data()
7834 {
7835         eval $LOGFS
7836         local runlvl=''
7837         local runlevel_path=$( type -p runlevel )
7838         if [[ -n $runlevel_path ]];then
7839                 runlvl="$( $runlevel_path | gawk '{ print $2 }' )"
7840         fi
7841         echo $runlvl
7842         eval $LOGFE
7843 }
7844
7845 # note: it appears that at least as of 2014-01-13, /etc/inittab is going to be used for
7846 # default runlevel in upstart/sysvinit. systemd default is not always set so check to see 
7847 # if it's linked.
7848 get_runlevel_default()
7849 {
7850         eval $LOGFS
7851         local default_runlvl=''
7852         local inittab='/etc/inittab'
7853         local systemd_default='/etc/systemd/system/default.target'
7854         local upstart_default='/etc/init/rc-sysinit.conf'
7855         
7856         # note: systemd systems do not necessarily have this link created
7857         if [[ -L $systemd_default  ]];then
7858                 default_runlvl=$( readlink $systemd_default )
7859                 if [[ -n $default_runlvl ]];then
7860                         default_runlvl=$( basename $default_runlvl )
7861                 fi
7862         # http://askubuntu.com/questions/86483/how-can-i-see-or-change-default-run-level
7863         # note that technically default can be changed at boot but for inxi purposes that does
7864         # not matter, we just want to know the system default
7865         elif [[ -e $upstart_default ]];then
7866                 # env DEFAULT_RUNLEVEL=2
7867                 default_runlvl=$( gawk -F '=' '/^env[[:space:]]+DEFAULT_RUNLEVEL/ {
7868                 print $2
7869                 }' $upstart_default )
7870         fi
7871         
7872         # handle weird cases where null but inittab exists
7873         if [[ -z $default_runlvl && -f $inittab ]];then
7874                 default_runlvl=$( gawk -F ':' '
7875                 /^id.*initdefault/ {
7876                         print $2
7877                 }' $inittab )
7878         fi
7879         echo $default_runlvl
7880         eval $LOGFE
7881 }
7882
7883 get_sensors_data()
7884 {
7885         eval $LOGFS
7886         
7887         
7888         local temp_array=''
7889                 
7890         IFS=$'\n'
7891         if [[ -n $Sensors_Data ]];then
7892                 # note: non-configured sensors gives error message, which we need to redirect to stdout
7893                 # also, -F ':' no space, since some cases have the data starting right after,like - :1287
7894                 A_SENSORS_DATA=( $( 
7895                 gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" '
7896                 BEGIN {
7897                         IGNORECASE=1
7898                         core0Temp="" # only if all else fails...
7899                         cpuTemp=""
7900                         cpuTempReal=""
7901                         fanWorking=""
7902                         indexCountaFanMain=0
7903                         indexCountaFanDefault=0
7904                         i=""
7905                         j=""
7906                         moboTemp=""
7907                         moboTempReal=""
7908                         psuTemp=""
7909                         separator=""
7910                         sysFanString=""
7911                         temp1=""
7912                         temp2=""
7913                         tempFanType="" # set to 1 or 2
7914                         tempUnit=""
7915                         tempWorking=""
7916                         tempWorkingUnit=""
7917                 }
7918                 # new data arriving: gpu temp in sensors, have to skip that
7919                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
7920                         while ( getline && !/^$/ ) {
7921                                 # do nothing, just skip it
7922                         }
7923                 }
7924                 # dumping the extra + signs after testing for them,  nobody has negative temps.
7925                 # also, note gawk treats Â° as a space, so we have to get the C/F data
7926                 # there are some guesses here, but with more sensors samples it will get closer.
7927                 # note: using arrays starting at 1 for all fan arrays to make it easier overall
7928                 # more validation because gensub if fails to get match returns full string, so
7929                 # we have to be sure we are working with the actual real string before assiging
7930                 # data to real variables and arrays. Extracting C/F degree unit as well to use
7931                 # when constructing temp items for array. 
7932                 # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign 
7933                 # used, but it is required in testing regex to avoid error.
7934                 /^(M\/B|MB|SIO|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7935                         moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 )
7936                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7937                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7938                                 tempUnit=tempWorkingUnit
7939                         }
7940                 }
7941                 /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7942                         cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7943                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7944                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7945                                 tempUnit=tempWorkingUnit
7946                         }
7947                 }
7948                 /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7949                         psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7950                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7951                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7952                                 tempUnit=tempWorkingUnit
7953                         }
7954                 }
7955                 $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7956                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7957                         if ( temp1 == "" || tempWorking > 0 ) {
7958                                 temp1=tempWorking
7959                         }
7960                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7961                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7962                                 tempUnit=tempWorkingUnit
7963                         }
7964                 }
7965                 $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7966                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7967                         if ( temp2 == "" || tempWorking > 0 ) {
7968                                 temp2=tempWorking
7969                         }
7970                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7971                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7972                                 tempUnit=tempWorkingUnit
7973                         }
7974                 }
7975                 
7976                 # final fallback if all else fails, funtoo user showed sensors putting
7977                 # temp on wrapped second line, not handled
7978                 /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7979                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7980                         if ( core0Temp == "" || tempWorking > 0 ) {
7981                                 core0Temp=tempWorking
7982                         }
7983                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7984                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7985                                 tempUnit=tempWorkingUnit
7986                         }
7987                 }
7988                 
7989                 # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before
7990                 # $2 starts (like so :1234 RPM), so skip that space test in regex
7991                 /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7992                         aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7993                 }
7994                 /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7995                         aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7996                 }
7997                 /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7998                         aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7999                 }
8000                 # note that the counters are dynamically set for fan numbers here
8001                 # otherwise you could overwrite eg aux fan2 with case fan2 in theory
8002                 # note: cpu/mobo/ps are 1/2/3
8003                 # NOTE: test: ! i in array does NOT work, this appears to be an awk/gawk bug
8004                 /^(AUX(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8005                         for ( i = 4; i < 7; i++ ){
8006                                 if ( i in aFanMain ){
8007                                         ##
8008                                 }
8009                                 else {
8010                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8011                                         break
8012                                 }
8013                         }
8014                 }
8015                 /^(AUX([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8016                         for ( i = 5; i < 30; i++ ){
8017                                 if ( i in aFanMain ) {
8018                                         ##
8019                                 }
8020                                 else {
8021                                         sysFanNu = i
8022                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8023                                         break
8024                                 }
8025                         }
8026                 }
8027                 # in rare cases syntax is like: fan1: xxx RPM
8028                 /^(FAN(1)?[ \t:])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8029                         aFanDefault[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8030                 }
8031                 /^FAN([2-9]|1[0-9])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8032                         fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8033                         sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 )
8034                         if ( sysFanNu ~ /^([0-9]+)$/ ) {
8035                                 # add to array if array index does not exist OR if number is > existing number
8036                                 if ( sysFanNu in aFanDefault ) {
8037                                         if ( fanWorking >= aFanDefault[sysFanNu] ) {
8038                                                 aFanDefault[sysFanNu]=fanWorking
8039                                         }
8040                                 }
8041                                 else {
8042                                         aFanDefault[sysFanNu]=fanWorking
8043                                 }
8044                         }
8045                 }
8046                 
8047                 END {
8048                         # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo:
8049                         # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment
8050                         if ( temp1 != "" && temp2 != "" ){
8051                                 if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) {
8052                                         tempFanType=userCpuNo
8053                                 }
8054                                 else {
8055                                         # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed
8056                                         # but only if other fan speed is 0
8057                                         if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) {
8058                                                 tempFanType=2
8059                                         }
8060                                         else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) {
8061                                                 tempFanType=1
8062                                         }
8063                                         # then handle the standard case if these fringe cases are false
8064                                         else if ( temp1 >= temp2 ) {
8065                                                 tempFanType=1
8066                                         }
8067                                         else {
8068                                                 tempFanType=2
8069                                         }
8070                                 }
8071                         }
8072                         # need a case for no temps at all reported, like with old intels
8073                         else if ( temp2 == "" && cpuTemp == "" ){
8074                                 if ( temp1 == "" && moboTemp == "" ){
8075                                         tempFanType=1
8076                                 }
8077                                 else if ( temp1 != "" && moboTemp == "" ){
8078                                         tempFanType=1
8079                                 }
8080                                 else if ( temp1 != "" && moboTemp != "" ){
8081                                         tempFanType=1
8082                                 }
8083                         }
8084                         
8085                         # then get the real cpu temp, best guess is hottest is real
8086                         if ( cpuTemp != "" ){
8087                                 cpuTempReal=cpuTemp
8088                         }
8089                         else if ( tempFanType != "" ){
8090                                 if ( tempFanType == 1 ){
8091                                         cpuTempReal=temp1
8092                                 }
8093                                 else {
8094                                         cpuTempReal=temp2
8095                                 }
8096                         }
8097                         else {
8098                                 cpuTempReal=temp1
8099                         }
8100                         # if all else fails, use core0 temp if it is present and cpu is null
8101                         if ( cpuTempReal == "" && core0Temp != "" ) {
8102                                 cpuTempReal=core0Temp
8103                         }
8104
8105                         # then the real mobo temp
8106                         if ( moboTemp != "" ){
8107                                 moboTempReal=moboTemp
8108                         }
8109                         else if ( tempFanType != "" ){
8110                                 if ( tempFanType == 1 ) {
8111                                         moboTempReal=temp2
8112                                 }
8113                                 else {
8114                                         moboTempReal=temp1
8115                                 }
8116                         }
8117                         else {
8118                                 moboTempReal=temp2
8119                         }
8120                         # then set the cpu fan speed
8121                         if ( aFanMain[1] == "" ) {
8122                                 # note, you cannot test for aFanDefault[1] or [2] != "" 
8123                                 # because that creates an array item in gawk just by the test itself
8124                                 if ( tempFanType == 1 && 1 in aFanDefault ) {
8125                                         aFanMain[1]=aFanDefault[1]
8126                                         aFanDefault[1]=""
8127                                 }
8128                                 else if ( tempFanType == 2 && 2 in aFanDefault ) {
8129                                         aFanMain[1]=aFanDefault[2]
8130                                         aFanDefault[2]=""
8131                                 }
8132                         }
8133
8134                         # then we need to get the actual numeric max array count for both fan arrays
8135                         for (i = 0; i <= 29; i++) {
8136                                 if ( i in aFanMain && i > indexCountaFanMain ) {
8137                                         indexCountaFanMain=i
8138                                 }
8139                         }
8140                         for (i = 0; i <= 14; i++) {
8141                                 if ( i in aFanDefault && i > indexCountaFanDefault ) {
8142                                         indexCountaFanDefault=i
8143                                 }
8144                         }
8145                         
8146                         # clear out any duplicates. Primary fan real trumps fan working always if same speed
8147                         for (i = 1; i <= indexCountaFanMain; i++) {
8148                                 if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) {
8149                                         for (j = 1; j <= indexCountaFanDefault; j++) {
8150                                                 if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) {
8151                                                         aFanDefault[j] = ""
8152                                                 }
8153                                         }
8154                                 }
8155                         }
8156
8157                         # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo
8158                         # note that gawk is returning true for some test cases when aFanDefault[j] < 5000
8159                         # which has to be a gawk bug, unless there is something really weird with arrays
8160                         # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually 
8161                         # assign that value below, the > 5000 test works again, and a print of the value
8162                         # shows the proper value, so the corruption might be internal in awk. 
8163                         # Note: gensub is the culprit I think, assigning type string for range 501-1000 but 
8164                         # type integer for all others, this triggers true for >
8165                         for (j = 1; j <= indexCountaFanDefault; j++) {
8166                                 if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) {
8167                                         aFanMain[2] = aFanDefault[j]
8168                                         aFanDefault[j] = ""
8169                                         # then add one if required for output
8170                                         if ( indexCountaFanMain < 2 ) {
8171                                                 indexCountaFanMain = 2
8172                                         }
8173                                 }
8174                         }
8175
8176                         # then construct the sys_fan string for echo, note that iteration 1
8177                         # makes: fanDefaultString separator null, ie, no space or ,
8178                         for (j = 1; j <= indexCountaFanDefault; j++) {
8179                                 fanDefaultString = fanDefaultString separator aFanDefault[j]
8180                                 separator=","
8181                         }
8182                         separator="" # reset to null for next loop
8183                         # then construct the sys_fan string for echo
8184                         for (j = 1; j <= indexCountaFanMain; j++) {
8185                                 fanMainString = fanMainString separator aFanMain[j]
8186                                 separator=","
8187                         }
8188                         
8189                         # and then build the temps:
8190                         if ( moboTempReal != "" ) {
8191                                 moboTempReal = moboTempReal tempUnit
8192                         }
8193                         if ( cpuTempReal != "" ) {
8194                                 cpuTempReal = cpuTempReal tempUnit
8195                         }
8196                         
8197                         # if they are ALL null, print error message. psFan is not used in output currently
8198                         if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) {
8199                                 print "No active sensors found. Have you configured your sensors yet?"
8200                         }
8201                         else {
8202                                 # then build array arrays: 
8203                                 print cpuTempReal "," moboTempReal "," psuTemp
8204                                 # this is for output, a null print line does NOT create a new array index in bash
8205                                 if ( fanMainString == "" ) {
8206                                         fanMainString=","
8207                                 }
8208                                 print fanMainString
8209                                 print fanDefaultString
8210                         }
8211                 }' <<< "$Sensors_Data" ) )
8212         fi
8213         
8214         IFS="$ORIGINAL_IFS"
8215         temp_array=${A_SENSORS_DATA[@]}
8216         log_function_data "A_SENSORS_DATA: $temp_array"
8217 #       echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
8218         eval $LOGFE
8219 }
8220
8221 get_sensors_output()
8222 {
8223         local sensors_path=$( type -p sensors ) sensors_data=''
8224         
8225         if [[ -n $sensors_path ]];then
8226                 sensors_data="$( $sensors_path 2>/dev/null )"
8227                 if [[ -n "$sensors_data" ]];then
8228                         # make sure the file ends in newlines then characters, the newlines are lost in the echo unless
8229                         # the data ends in some characters
8230                         sensors_data="$sensors_data\n\n###" 
8231                 fi
8232         fi
8233         echo -e "$sensors_data"
8234 }
8235
8236 get_shell_data()
8237 {
8238         eval $LOGFS
8239
8240         local shell_type="$( ps -p $PPID -o comm= 2>/dev/null )"
8241         local shell_version='' 
8242         
8243         if [[ $B_EXTRA_DATA == 'true' && -n $shell_type ]];then
8244                 case $shell_type in
8245                         bash)
8246                                 shell_version=$( get_de_app_version "$shell_type" "^GNU[[:space:]]bash,[[:space:]]version" "4" | \
8247                                 sed $SED_RX 's/(\(.*|-release|-version)//' )
8248                                 ;;
8249                         # csh/dash use dpkg package version data, debian/buntu only
8250                         csh)
8251                                 shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
8252                                 ;;
8253                         dash)
8254                                 shell_version=$( get_de_app_version "$shell_type" "$shell_type" "3" )
8255                                 ;;
8256                         ksh)
8257                                 shell_version=$( get_de_app_version "$shell_type" "version" "5" )
8258                                 ;;
8259                         tcsh)
8260                                 shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
8261                                 ;;
8262                         zsh)
8263                                 shell_version=$( get_de_app_version "$shell_type" "^zsh" "2" )
8264                                 ;;
8265                 esac
8266         fi
8267         if [[ -n $shell_version ]];then
8268                 shell_type="$shell_type $shell_version"
8269         fi
8270         echo $shell_type
8271         
8272         eval $LOGFS
8273 }
8274
8275 get_shell_parent()
8276 {
8277         eval $LOGFS
8278         local shell_parent='' script_parent='' 
8279         
8280         # removed --no-headers to make bsd safe, adding in -j to make output the same
8281         script_parent=$( ps -j -fp $PPID 2>/dev/null | gawk '/'"$PPID"'/ { print $3 }' )
8282         log_function_data "script parent: $script_parent"
8283         shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
8284         # no idea why have to do script_parent action twice in su case, but you do, oh well.
8285         if [[ $shell_parent == 'su' ]];then
8286                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
8287                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
8288                 shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
8289         fi
8290         echo $shell_parent
8291         log_function_data "shell parent final: $shell_parent"
8292         eval $LOGFE
8293 }
8294
8295 # this will be used for some bsd data types
8296 # args: $1 - option type
8297 get_sysctl_data()
8298 {
8299         eval $LOGFS
8300         
8301         local sysctl_data=''
8302         
8303         if [[ $B_SYSCTL ]];then
8304                 sysctl_data="$( sysctl -$1 )"
8305         fi
8306         # log_function_data "sysctl_data: $sysctl_data"
8307         echo "$sysctl_data"
8308         eval $LOGFE
8309 }
8310
8311 get_tty_console_irc()
8312 {
8313         eval $LOGFS
8314         local tty_number=''
8315         if [[ -n ${IRC_CLIENT} ]];then
8316                 tty_number=$( gawk '
8317                         BEGIN {
8318                                 IGNORECASE=1
8319                         }
8320                         # if multiple irc clients open, can give wrong results
8321                         # so make sure to also use the PPID number to get the right tty
8322                         /.*'$PPID'.*'${IRC_CLIENT}'/ {
8323                                 gsub(/[^0-9]/, "", $7)
8324                                 print $7
8325                                 exit
8326                         }' <<< "$Ps_aux_Data" )
8327         fi
8328         log_function_data "tty_number: $tty_number"
8329         echo $tty_number
8330         eval $LOGFE
8331 }
8332
8333 get_tty_number()
8334 {
8335         eval $LOGFS
8336         
8337         local tty_number=$( basename "$( tty 2>/dev/null )" | sed 's/[^0-9]*//g' )
8338         
8339         echo $tty_number
8340         
8341         eval $LOGFE
8342 }
8343
8344 get_unmounted_partition_data()
8345 {
8346         eval $LOGFS
8347         local a_unmounted_working='' mounted_partitions='' separator='|' unmounted_fs=''
8348         local dev_working='' uuid_working='' label_working='' a_raid_working='' raid_partitions=''
8349         
8350         if [[ $B_PARTITIONS_FILE == 'true' ]];then
8351                 # set dev disk label/uuid data globals
8352                 get_partition_dev_data 'label'
8353                 get_partition_dev_data 'uuid'
8354                 # load the raid data array here so we can exclude its partitions
8355                 if [[ $B_RAID_SET != 'true' ]];then
8356                         get_raid_data
8357                 fi
8358                 # sr0 type cd drives are showing up now as unmounted partitions
8359                 mounted_partitions="scd[0-9]+|sr[0-9]+|cdrom[0-9]*|cdrw[0-9]*|dvd[0-9]*|dvdrw[0-9]*"
8360                 # create list for slicing out the mounted partitions
8361                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
8362                 do
8363                         IFS=","
8364                         a_unmounted_working=( ${A_PARTITION_DATA[i]} )
8365                         IFS="$ORIGINAL_IFS"
8366                         if [[ -n ${a_unmounted_working[6]} ]];then
8367                                 mounted_partitions="$mounted_partitions$separator${a_unmounted_working[6]}"
8368                         fi
8369                 done
8370                 # now we need to exclude the mdraid partitions from the unmounted partition output as well
8371                 for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
8372                 do
8373                         IFS=","
8374                         a_raid_working=( ${A_RAID_DATA[i]} )
8375                         IFS="$ORIGINAL_IFS"
8376                         if [[ -n ${a_raid_working[3]} ]];then
8377                                 raid_partitions=$( sed $SED_RX 's/(\([^\)]*\)|\[[^\]]*\])//g' <<< ${a_raid_working[3]}\
8378                                 | sed 's/[[:space:]]\+/|/g' )
8379                                 mounted_partitions="$mounted_partitions$separator$raid_partitions"
8380                         fi
8381                 done
8382         
8383                 A_UNMOUNTED_PARTITION_DATA=( $( grep -Ev '[[:space:]]('$mounted_partitions')$' $FILE_PARTITIONS | gawk '
8384                 BEGIN {
8385                         IGNORECASE=1
8386                 }
8387                 # note that size 1 means it is a logical extended partition container
8388                 # lvm might have dm-1 type syntax
8389                 # need to exclude loop type file systems, squashfs for example
8390                 /[a-z][0-9]+$|dm-[0-9]+$/ && $3 != 1 && $NF !~ /loop/ {
8391                         size = sprintf( "%.2f", $3*1024/1000**3 )
8392                         print $4 "," size "G"
8393                 }' ) )
8394
8395                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
8396                 do
8397                         IFS=","
8398                         a_unmounted_working=( ${A_UNMOUNTED_PARTITION_DATA[i]} )
8399                         IFS="$ORIGINAL_IFS"
8400                         
8401                         label_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_LABEL"  | gawk '{
8402                                 print $(NF - 2)
8403                         }' )
8404                         uuid_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_UUID"  | gawk '{
8405                                 print $(NF - 2)
8406                         }' )
8407                         unmounted_fs=$( get_unmounted_partition_filesystem "/dev/${a_unmounted_working[0]}" )
8408                         
8409                         IFS=","
8410                         A_UNMOUNTED_PARTITION_DATA[i]=${a_unmounted_working[0]}","${a_unmounted_working[1]}","$label_working","$uuid_working","$unmounted_fs
8411                         IFS="$ORIGINAL_IFS"
8412                 done
8413         fi
8414 #       echo "${A_PARTITION_DATA[@]}"
8415 #       echo "${A_UNMOUNTED_PARTITION_DATA[@]}"
8416         eval $LOGFE
8417 }
8418
8419 # a few notes, normally file -s requires root, but you can set user rights in /etc/sudoers.
8420 # list of file systems: http://en.wikipedia.org/wiki/List_of_file_systems
8421 # args: $1 - /dev/<disk><part> to be tested for
8422 get_unmounted_partition_filesystem()
8423 {
8424         eval $LOGFS
8425         local partition_filesystem='' sudo_command=''
8426         
8427         if [[ $B_FILE_TESTED != 'true' ]];then
8428                 B_FILE_TESTED='true'
8429                 FILE_PATH=$( type -p file )
8430         fi
8431         
8432         if [[ $B_SUDO_TESTED != 'true' ]];then
8433                 B_SUDO_TESTED='true'
8434                 SUDO_PATH=$( type -p sudo )
8435         fi
8436         
8437         if [[ -n $FILE_PATH && -n $1 ]];then
8438                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
8439                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
8440                 # important: -n makes it non interactive, no prompt for password
8441                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
8442                         sudo_command='sudo -n '
8443                 fi
8444                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
8445                 # note the hack that simply slices out the first line if > 1 items found in string
8446                 # also, if grub/lilo is on partition boot sector, no file system data is available
8447                 # BSD fix: -Eio -Em 1
8448                 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 '.*' )
8449                 if [[ -n $partition_filesystem ]];then
8450                         echo $partition_filesystem
8451                 fi
8452         fi
8453         eval $LOGFE
8454 }
8455
8456 ## return uptime string
8457 get_uptime()
8458 {
8459         eval $LOGFS
8460         ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
8461         local uptime_value="$( uptime | gawk '{
8462                 a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
8463                 print a
8464         }' )"
8465         echo "$uptime_value"
8466         log_function_data "uptime_value: $uptime_value"
8467         eval $LOGFE
8468 }
8469
8470 get_weather_data()
8471 {
8472         eval $LOGFS
8473         
8474         local location_site='http://geoip.ubuntu.com/lookup'
8475         local weather_feed='http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query='
8476         local weather_spider='http://wunderground.com/'
8477         local data_grab_error='' wget_error=0 
8478         local b_test_loc=false b_test_weather=false b_debug=false
8479         local test_dir="$HOME/bin/scripts/inxi/data/weather/"
8480         local test_location='location2.xml' test_weather='weather-feed.xml'
8481         local location_data='' location='' weather_data='' location_array_value='' a_location=''
8482         local weather_array_value='' site_elevation='' temp_array=''
8483         
8484         # first we get the location data, once that is parsed and handled, we move to getting the 
8485         # actual weather data, assuming no errors
8486         if [[ -n $ALTERNATE_WEATHER_LOCATION ]];then
8487                 # note, this api does not support spaces in names, replace spaces with + sign.
8488                 location=$ALTERNATE_WEATHER_LOCATION
8489                 # echo $ALTERNATE_WEATHER_LOCATION;exit
8490         else
8491                 if [[ $b_test_loc != 'true' ]];then
8492                         location_data=$( wget -q -t 1 -T $WGET_TIMEOUT -O- $location_site || wget_error=$? )
8493                         log_function_data "$location_data"
8494                         if [[ $wget_error -ne 0 ]];then
8495                                 data_grab_error="Error: location server up but download error - wget: $wget_error"
8496                         fi
8497                         wget_error=0
8498                 else
8499                         if [[ -f $test_dir$test_location ]];then
8500                                 location_data="$( cat $test_dir$test_location )"
8501                         else
8502                                 data_grab_error="Error: location xml local file not found."
8503                         fi
8504                 fi
8505                 if [[ -n $data_grab_error ]];then
8506                         :
8507                 elif [[ -z $( grep -i '<Response' <<< $location_data ) ]];then
8508                         data_grab_error="Error: location downloaded but data contains no xml."
8509                 else
8510                         # clean up xml and make easy to process with newlines, note, bsd sed has no support for inserting
8511                         # \n dircctly so we have to use this hack
8512                         # location_data="$( sed $SED_RX 's|><|>\n<|g' <<< $location_data )"
8513                         location_data="$( sed $SED_RX 's|><|>\
8514 <|g' <<< $location_data )"
8515                         # echo -e "ld:\n$location_data"
8516                         location_array_value=$( gawk '
8517                         function clean(data) {
8518                                 returnData=""
8519                                 # some lines might be empty, so ignore those
8520                                 if (data !~ /^<[^>]+>$/ ) {
8521                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8522                                 }
8523                                 return returnData
8524                         }
8525                         BEGIN {
8526                                 IGNORECASE=1
8527                                 locationString=""
8528                                 countryCode=""
8529                                 countryCode3=""
8530                                 countryName=""
8531                                 regionCode=""
8532                                 regionName=""
8533                                 city=""
8534                                 postalCode=""
8535                                 latitude=""
8536                                 longitude=""
8537                                 timeZone=""
8538                                 areaCode=""
8539                         }
8540                         /CountryCode/ {
8541                                 if ( $0 ~ /CountryCode3/ ){
8542                                         countryCode3=clean($0)
8543                                 }
8544                                 else {
8545                                         countryCode=clean($0)
8546                                 }
8547                         }
8548                         /CountryName/ {
8549                                 countryName = clean($0)
8550                         }
8551                         /RegionCode/ {
8552                                 regionCode = clean($0)
8553                         }
8554                         /RegionName/ {
8555                                 regionName = clean($0)
8556                         }
8557                         /City/ {
8558                                 city = clean($0)
8559                         }
8560                         /ZipPostalCode/ {
8561                                 postalCode = clean($0)
8562                         }
8563                         /Latitude/ {
8564                                 latitude = clean($0)
8565                         }
8566                         /Longitude/ {
8567                                 longitude = clean($0)
8568                         }
8569                         /TimeZone/ {
8570                                 timeZone = clean($0)
8571                         }
8572                         END {
8573                                 locationString = city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
8574                                 locationString = locationString  ";" latitude "," longitude ";" postalCode ";" timeZone
8575                                 print locationString
8576                         }' <<< "$location_data" )
8577                 fi
8578                 A_WEATHER_DATA[0]=$location_array_value
8579                 IFS=";"
8580                 a_location=( ${A_WEATHER_DATA[0]} )
8581                 IFS="$ORIGINAL_IFS"
8582                 
8583                 # assign location, cascade from most accurate
8584                 # latitude,longitude first
8585                 if [[ -n ${a_location[6]} ]];then
8586                         location="${a_location[6]}"
8587                 # city,state next
8588                 elif [[ -n ${a_location[0]} && -n ${a_location[1]} ]];then
8589                         location="${a_location[0]},${a_location[1]}"
8590                 # postal code last, that can be a very large region
8591                 elif [[ -n ${a_location[7]} ]];then
8592                         location=${a_location[7]}
8593                 fi
8594         fi
8595         if [[ $b_debug == 'true' ]];then
8596                 echo -e "location array:\n${A_WEATHER_DATA[0]}"
8597                 echo "location: $location"
8598         fi
8599         log_function_data "location: $location"
8600         
8601         if [[ -z $location && -z $data_grab_error ]];then
8602                 data_grab_error="Error: location data downloaded but no location detected."
8603         fi
8604
8605         # now either dump process or go on to get weather data
8606         if [[ -z $data_grab_error ]];then
8607                 if [[ $b_test_weather != 'true' ]];then
8608                         weather_data="$( wget -q -t 1 -T $WGET_TIMEOUT -O- $weather_feed"$location" || wget_error=$? )"
8609                         if [[ $wget_error -ne 0 ]];then
8610                                 data_grab_error="Error: weather server up but download error - wget: $wget_error"
8611                         fi
8612                         log_function_data "$weather_data"
8613                 else
8614                         if [[ -f $test_dir$test_weather ]];then
8615                                 weather_data="$( cat $test_dir$test_weather)"
8616                         else
8617                                 data_grab_error="Error: weather feed xml local file not found."
8618                         fi
8619                 fi
8620                 if [[ -z $data_grab_error && -z $( grep -i '<current_observation' <<< $weather_data ) ]];then
8621                         data_grab_error="Error: weather data downloaded but shows no xml start."
8622                 fi
8623                 if [[ -z $data_grab_error ]];then
8624                         # trim off zeros
8625                         weather_data=$( sed 's/^[[:space:]]*//' <<< "$weather_data" )
8626                         site_elevation=$( grep -im 1 '<elevation>' <<< "$weather_data" | sed $SED_RX -e 's/<[^>]*>//g' \
8627                         -e 's/\.[0-9]*//' )
8628                         # we need to grab the location data from the feed for remote checks 
8629                         if [[ -n $ALTERNATE_WEATHER_LOCATION && -n $weather_data ]];then
8630                                 location_data=$( sed -e '/<current_observation>/,/<display_location>/d' -e '/<\/display_location>/,/<\/current_observation>/d' <<< "$weather_data" )
8631                                 # echo -e "ld1:\n$location_data"
8632                                 A_WEATHER_DATA[0]=$( gawk '
8633                                 function clean(data) {
8634                                         returnData=""
8635                                         # some lines might be empty, so ignore those
8636                                         if (data !~ /^<[^>]+>$/ ) {
8637                                                 returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8638                                                 gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
8639                                         }
8640                                         return returnData
8641                                 }
8642                                 BEGIN {
8643                                         IGNORECASE=1
8644                                         city=""
8645                                         state=""
8646                                         country=""
8647                                 }
8648                                 /<city>/ {
8649                                         city=clean($0)
8650                                 }
8651                                 /<state>/ {
8652                                         state=clean($0)
8653                                 }
8654                                 /<country>/ {
8655                                         country=clean($0)
8656                                 }
8657                                 END {
8658                                         print city ";" state ";;;;" country
8659                                 }' <<< "$location_data" )
8660                                 # echo -e "location:\n${A_WEATHER_DATA[0]}"
8661                         fi
8662                         
8663                         # clean off everything before/after observation_location
8664                         weather_data=$( sed -e '/<current_observation>/,/<observation_location>/d' \
8665                         -e '/<icons>/,/<\/current_observation>/d' <<< "$weather_data" -e 's/^[[:space:]]*$//g' -e '/^$/d' )
8666                         
8667                         # echo "$weather_data";exit 
8668                         weather_array_value=$( gawk -v siteElevation="$site_elevation" '
8669                         function clean(data) {
8670                                 returnData=""
8671                                 # some lines might be empty, so ignore those
8672                                 if (data !~ /^<[^>]+>$/ ) {
8673                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8674                                         gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
8675                                 }
8676                                 return returnData
8677                         }
8678                         BEGIN {
8679                                 IGNORECASE=1
8680                                 observationTime=""
8681                                 localTime=""
8682                                 weather=""
8683                                 tempString=""
8684                                 humidity=""
8685                                 windString=""
8686                                 pressureString=""
8687                                 dewpointString=""
8688                                 heatIndexString=""
8689                                 windChillString=""
8690                                 weatherString=""
8691                         }
8692                         /observation_time>/ {
8693                                 observationTime=clean($0)
8694                                 sub(/Last Updated on /, "", observationTime )
8695                         }
8696                         /local_time>/ {
8697                                 localTime=clean($0)
8698                         }
8699                         /<weather/ {
8700                                 weather=clean($0)
8701                         }
8702                         /temperature_string/ {
8703                                 tempString=clean($0)
8704                         }
8705                         /relative_humidity/ {
8706                                 humidity=clean($0)
8707                         }
8708                         /wind_string/ {
8709                                 windString=clean($0)
8710                         }
8711                         /pressure_string/ {
8712                                 pressureString=clean($0)
8713                         }
8714                         /heat_index_string/ {
8715                                 heatIndexString=clean($0)
8716                         }
8717                         /windchill_string/ {
8718                                 windChillString=clean($0)
8719                         }
8720                         END {
8721                                 weatherString = observationTime ";" localTime ";" weather ";" tempString ";" humidity 
8722                                 weatherString = weatherString ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
8723                                 weatherString = weatherString ";" windChillString ";" siteElevation
8724                                 print weatherString
8725                         }' <<< "$weather_data" )
8726                 fi
8727                 if [[ -z $weather_array_value ]];then
8728                         data_grab_error="Error: weather info downloaded but no data detected."
8729                 else
8730                         A_WEATHER_DATA[1]=$weather_array_value
8731                 fi
8732         fi
8733         # now either dump process or go on to get weather data
8734         if [[ -n $data_grab_error ]];then
8735                 A_WEATHER_DATA=$data_grab_error
8736                 log_function_data "data grab error: $data_grab_error"
8737         fi
8738         
8739         if [[ $b_debug == 'true' ]];then
8740                 echo "site_elevation: $site_elevation"
8741                 echo "${A_WEATHER_DATA[1]}"
8742         fi
8743         temp_array=${A_WEATHER_DATA[@]}
8744         log_function_data "A_WEATHER_DATA: $temp_array"
8745         
8746         eval $LOGFE
8747 }
8748 # ALTERNATE_WEATHER_LOCATION='portland,or'
8749 # get_weather_data;exit
8750
8751 #### -------------------------------------------------------------------
8752 #### special data handling for specific options and conditions
8753 #### -------------------------------------------------------------------
8754
8755 # args: $1 - string to strip color code characters out of
8756 # returns count of string length minus colors
8757 calculate_line_length()
8758 {
8759         local string=$1
8760         # ansi: \e[1;34m irc: \x0312
8761         string=$( sed -e "s/\x1b\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g" -e "s/\\\x0[0-9]\{1,3\}//g" <<< $string )
8762         count=${#string}
8763         echo $count
8764 }
8765
8766 ## multiply the core count by the data to be calculated, bmips, cache
8767 # args: $1 - string to handle; $2 - cpu count
8768 calculate_multicore_data()
8769 {
8770         eval $LOGFS
8771         local string_number=$1 string_data=''
8772
8773         if [[ -n $( grep -Ei '( mb| kb)' <<< $1 ) ]];then
8774                 string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output
8775                 string_number=$( gawk '{print $1}' <<< $1 )
8776         fi
8777         # handle weird error cases where it's not a number
8778         if [[ -n $( grep -E '^[0-9\.,]+$' <<< $string_number ) ]];then
8779                 string_number=$( echo $string_number $2 | gawk '{
8780                         total = $1*$2
8781                         print total
8782                 }' )
8783         elif [[ $string_number == '' ]];then
8784                 string_number='N/A'
8785         else
8786                 # I believe that the above returns 'unknown' by default so no need for extra text
8787                 string_number="$string_number "
8788         fi
8789         echo "$string_number$string_data"
8790         log_function_data "string_numberstring_data: $string_number$string_data"
8791         eval $LOGFE
8792 }
8793
8794 # prints out shortened list of flags, the main ones of interest
8795 # args: $1 - string of cpu flags to process
8796 process_cpu_flags()
8797 {
8798         eval $LOGFS
8799         
8800         local cpu_flags_working=$1
8801         local bits=$( uname -m | grep 64 )
8802         
8803         # no need to show pae for 64 bit cpus, it's pointless
8804         if [[ -n $bits ]];then
8805                 cpu_flags_working=$( sed 's/[[:space:]]*pae//' <<< "$cpu_flags_working" )
8806         fi
8807         # must have a space after last item in list for RS=" "
8808         cpu_flags_working="$cpu_flags_working "
8809         
8810         # nx = AMD stack protection extensions
8811         # lm = Intel 64bit extensions
8812         # sse, sse2, pni = sse1,2,3,4,5 gfx extensions
8813         # svm = AMD pacifica virtualization extensions
8814         # vmx = Intel IVT (vanderpool) virtualization extensions
8815         cpu_flags=$( gawk '
8816         BEGIN {
8817                 RS=" "
8818                 count = 0
8819                 i = 1 # start at one because of for increment issue
8820                 flag_string = ""
8821         }
8822         
8823         /^(lm|nx|pae|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/ {
8824                 if ( $0 == "pni" ){
8825                         a_flags[i] = "sse3"
8826                 }
8827                 else {
8828                         a_flags[i] = $0
8829                 }
8830                 i++
8831         }
8832         END {
8833                 count = asort( a_flags )
8834                 # note: why does gawk increment before the loop and not after? weird.
8835                 for ( i=0; i <= count; i++ ){
8836                         if ( flag_string == "" ) {
8837                                 flag_string = a_flags[i] 
8838                         }
8839                         else {
8840                                 flag_string = flag_string " " a_flags[i]
8841                         }
8842                 }
8843                 print flag_string
8844         }' <<< "$cpu_flags_working" )
8845
8846         #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' '))
8847         if [[ -z $cpu_flags ]];then
8848                 cpu_flags="-"
8849         fi
8850         echo "$cpu_flags"
8851         log_function_data "cpu_flags: $cpu_flags"
8852         eval $LOGFE
8853 }
8854
8855 #### -------------------------------------------------------------------
8856 #### print and processing of output data
8857 #### -------------------------------------------------------------------
8858
8859 #### MASTER PRINT FUNCTION - triggers all line item print functions
8860 ## main function to print out, master for all sub print functions.
8861 print_it_out()
8862 {
8863         eval $LOGFS
8864         # note that print_it_out passes local variable values on to its children,
8865         # and in some cases, their children, with Lspci_v_Data
8866         local Lspci_v_Data='' Lspci_n_Data='' # only for verbose
8867         local Sysctl_a_Data='' Dmesg_Boot_Data=''
8868         
8869         if [[ -n $BSD_TYPE ]];then
8870                 Sysctl_a_Data="$( get_sysctl_data 'a' )"
8871                 Dmesg_Boot_Data="$( get_dmesg_boot_data )"
8872         fi
8873
8874         if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then
8875                 print_short_data
8876         else
8877                 Lspci_v_Data="$( get_lspci_data 'v' )"
8878                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
8879                         Lspci_n_Data="$( get_lspci_data 'n' )"
8880                 fi
8881                 if [[ $B_SHOW_SYSTEM == 'true' ]];then
8882                         print_system_data
8883                 fi
8884                 if [[ $B_SHOW_MACHINE == 'true' ]];then
8885                         print_machine_data
8886                 fi
8887                 if [[ $B_SHOW_WEATHER == 'true' ]];then
8888                         print_weather_data
8889                 fi
8890                 if [[ $B_SHOW_BASIC_CPU == 'true' || $B_SHOW_CPU == 'true' ]];then
8891                         print_cpu_data
8892                 fi
8893                 if [[ $B_SHOW_GRAPHICS == 'true' ]];then
8894                         print_graphics_data
8895                 fi
8896                 if [[ $B_SHOW_AUDIO == 'true' ]];then
8897                         print_audio_data
8898                 fi
8899                 if [[ $B_SHOW_NETWORK == 'true' ]];then
8900                         print_networking_data
8901                 fi
8902                 if [[ $B_SHOW_DISK_TOTAL == 'true' || $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
8903                         print_hard_disk_data
8904                 fi
8905                 if [[ $B_SHOW_PARTITIONS == 'true' ]];then
8906                         print_partition_data
8907                 fi
8908                 if [[ $B_SHOW_RAID == 'true' || $B_SHOW_BASIC_RAID == 'true' ]];then
8909                         print_raid_data
8910                 fi
8911                 if [[ $B_SHOW_UNMOUNTED_PARTITIONS == 'true' ]];then
8912                         print_unmounted_partition_data
8913                 fi
8914                 if [[ $B_SHOW_SENSORS == 'true' ]];then
8915                         print_sensors_data
8916                 fi
8917                 if [[ $B_SHOW_REPOS == 'true' ]];then
8918                         print_repo_data
8919                 fi
8920                 if [[ $B_SHOW_PS_CPU_DATA == 'true' || $B_SHOW_PS_MEM_DATA == 'true' ]];then
8921                         print_ps_data
8922                 fi
8923                 if [[ $B_SHOW_INFO == 'true' ]];then
8924                         print_info_data
8925                 fi
8926         fi
8927         eval $LOGFE
8928 }
8929
8930 #### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0
8931 # all the get data stuff is loaded here to keep execution time down for single line print commands
8932 # these will also be loaded in each relevant print function for long output
8933 print_short_data()
8934 {
8935         eval $LOGFS
8936         local current_kernel=$( get_kernel_version ) 
8937         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
8938         local short_data='' i='' b_background_black='false'
8939         local memory=$( get_memory_data )
8940         local up_time="$( get_uptime )"
8941
8942         # set A_CPU_CORE_DATA
8943         get_cpu_core_count
8944         local cpc_plural='' cpu_count_print='' model_plural=''
8945         local cpu_physical_count=${A_CPU_CORE_DATA[0]}
8946         local cpu_core_count=${A_CPU_CORE_DATA[3]}
8947         local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
8948         local cpu_type=${A_CPU_CORE_DATA[2]}
8949
8950         if [[ $cpu_physical_count -gt 1 ]];then
8951                 cpc_plural='(s)'
8952                 model_plural='s'
8953                 cpu_count_print="$cpu_physical_count "
8954         fi
8955
8956         local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
8957 #       local cpu_core_count=${A_CPU_CORE_DATA[0]}
8958
8959         # load A_HDD_DATA
8960         get_hdd_data_basic
8961         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
8962         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
8963         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
8964         IFS=","
8965         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
8966         IFS="$ORIGINAL_IFS"
8967         local hdd_capacity=${a_hdd_basic_working[0]}
8968         local hdd_used=${a_hdd_basic_working[1]}
8969
8970         # load A_CPU_DATA
8971         get_cpu_data
8972
8973         IFS=","
8974         local a_cpu_working=(${A_CPU_DATA[0]})
8975         IFS="$ORIGINAL_IFS"
8976         local cpu_model="${a_cpu_working[0]}"
8977         ## assemble data for output
8978         local cpu_clock="${a_cpu_working[1]}" # old CPU3
8979         # this gets that weird min/max final array item, which almost never contains any data of use
8980         local min_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
8981         local min_max_clock=${A_CPU_DATA[$min_max_clock_nu]}
8982         # this handles the case of for example ARM cpus, which will not have data for
8983         # min/max, since they don't have speed. Since that sets a flag, not found, just
8984         # look for that and use the speed from the first array array, same where we got 
8985         # model from
8986         if [[ "$min_max_clock" == 'N/A' && ${a_cpu_working[1]} != '' ]];then
8987                 min_max_clock="${a_cpu_working[1]} MHz"
8988         fi
8989         local patch_version_number=$( get_patch_version_string )
8990
8991         #set_color_scheme 12
8992         if [[ $B_RUNNING_IN_SHELL == 'false' ]];then
8993                 for i in $C1 $C2 $CN
8994                 do
8995                         case "$i" in
8996                                 "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN")
8997                                         b_background_black='true'
8998                                         ;;
8999                         esac
9000                 done
9001                 if [[ $b_background_black == 'true' ]];then
9002                         for i in C1 C2 CN
9003                         do
9004                                 ## these need to be in quotes, don't know why
9005                                 if [[ ${!i} == $NORMAL ]];then
9006                                         declare $i="${!i}15,1"
9007                                 else
9008                                         declare $i="${!i},1"
9009                                 fi
9010                         done
9011                         #C1="${C1},1"; C2="${C2},1"; CN="${CN},1"
9012                 fi
9013         fi
9014         short_data="${C1}CPU$cpc_plural${C2}${SEP1}${cpu_data_string} ${cpu_model}$model_plural (${cpu_type}) clocked at ${min_max_clock}${SEP2}${C1}Kernel${C2}${SEP1}${current_kernel}${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}"
9015
9016         if [[ $SHOW_IRC -gt 0 ]];then
9017                 short_data="${short_data}${C1}Client${C2}${SEP1}${IRC_CLIENT}${IRC_CLIENT_VERSION}${SEP2}"
9018         fi
9019         short_data="${short_data}${C1}$SCRIPT_NAME${C2}${SEP1}$SCRIPT_VERSION_NUMBER$patch_version_number${SEP2}${CN}"
9020         if [[ $SCHEME -gt 0 ]];then
9021                 short_data="${short_data} $NORMAL"
9022         fi
9023         print_screen_output "$short_data"
9024         eval $LOGFE
9025 }
9026
9027 #### LINE ITEM PRINT FUNCTIONS
9028
9029 # print sound card data
9030 print_audio_data()
9031 {
9032         eval $LOGFS
9033         local i='' card_id='' audio_data='' a_audio_data='' port_data='' pci_bus_id='' card_string=''
9034         local a_audio_working='' audio_driver='' alsa_data='' port_plural='' module_version='' chip_id=''
9035         local bus_usb_text='' bus_usb_id='' line_starter='Audio:' alsa='' alsa_version='' print_data=''
9036         local driver=''
9037         # set A_AUDIO_DATA and get alsa data
9038         if [[ $BSD_TYPE == 'bsd' ]];then
9039                 if [[ $B_PCICONF_SET == 'false' ]];then
9040                         get_pciconf_data
9041                 fi
9042                 get_pciconf_card_data 'audio'
9043         else
9044                 get_audio_data
9045         fi
9046         
9047         get_audio_alsa_data
9048         # alsa driver data now prints out no matter what
9049         if [[ -n $A_ALSA_DATA ]];then
9050                 IFS=","
9051                 if [[ -n ${A_ALSA_DATA[0]} ]];then
9052                         alsa=${A_ALSA_DATA[0]}
9053                 else
9054                         alsa='N/A'
9055                 fi
9056                 if [[ -n ${A_ALSA_DATA[1]} ]];then
9057                         alsa_version=${A_ALSA_DATA[1]}
9058                 else
9059                         alsa_version='N/A'
9060                 fi
9061                 alsa_data="${C1}Sound:${C2} $alsa ${C1}ver$SEP3${C2} $alsa_version"
9062                 IFS="$ORIGINAL_IFS"
9063         fi
9064         # note, error handling is done in the get function, so this will never be null, but
9065         # leaving the test just in case it's changed.
9066         if [[ -n ${A_AUDIO_DATA[@]} ]];then
9067                 for (( i=0; i< ${#A_AUDIO_DATA[@]}; i++ ))
9068                 do
9069                         IFS=","
9070                         a_audio_working=( ${A_AUDIO_DATA[i]} )
9071                         IFS="$ORIGINAL_IFS"
9072                         port_data=''
9073                         audio_driver=''
9074                         audio_data=''
9075                         card_string=''
9076                         port_plural=''
9077                         module_version=''
9078                         pci_bus_id=''
9079                         bus_usb_text=''
9080                         bus_usb_id=''
9081                         print_data=''
9082                         card_id=''
9083                         chip_id=''
9084                         
9085                         if [[ ${#A_AUDIO_DATA[@]} -gt 1 ]];then
9086                                 card_id="-$(( $i + 1 ))"
9087                         fi
9088                         if [[ $BSD_TYPE != 'bsd' ]];then
9089                                 if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then
9090                                         module_version=$( print_module_version "${a_audio_working[3]}" 'audio' )
9091                                 elif [[ -n ${a_audio_working[1]} && $B_EXTRA_DATA == 'true' ]];then
9092                                         module_version=$( print_module_version "${a_audio_working[1]}" 'audio' )
9093                                 fi
9094                         fi
9095                         # we're testing for the presence of the 2nd array item here, which is the driver name
9096                         if [[ -n ${a_audio_working[1]} ]];then
9097                                 # note: linux drivers can have numbers, like tg3
9098                                 if [[ $BSD_TYPE == 'bsd' ]];then
9099                                         driver=$( sed 's/[0-9]$//' <<< ${a_audio_working[1]} )
9100                                 else
9101                                         driver=${a_audio_working[1]}
9102                                 fi
9103                                 audio_driver="${C1}driver$SEP3${C2} ${driver} "
9104                         fi
9105                         if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then
9106                                 if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then
9107                                         port_plural='s'
9108                                 fi
9109                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_audio_working[2]} "
9110                         fi
9111                         if [[ -n ${a_audio_working[4]} && $B_EXTRA_DATA == 'true' ]];then
9112                                 if [[ ${a_audio_working[1]} != 'USB Audio' ]];then
9113                                         bus_usb_text='bus-ID'
9114                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9115                                                 if [[ $BSD_TYPE != 'bsd' ]];then
9116                                                         chip_id=$( get_lspci_chip_id "${a_audio_working[4]}" )
9117                                                 else
9118                                                         chip_id=${a_audio_working[6]}
9119                                                 fi
9120                                         fi
9121                                 else
9122                                         bus_usb_text='usb-ID'
9123                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9124                                                 chip_id=${a_audio_working[5]}
9125                                         fi
9126                                 fi
9127                                 bus_usb_id=${a_audio_working[4]}
9128                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id "
9129                                 if [[ -n $chip_id ]];then
9130                                         chip_id="${C1}chip-ID$SEP3${C2} $chip_id "
9131                                 fi
9132                         fi
9133                         if [[ -n ${a_audio_working[0]} ]];then
9134                                 card_string="${C1}Card$card_id:${C2} ${a_audio_working[0]} "
9135                                 audio_data="$audio_driver$port_data$pci_bus_id$chip_id"
9136                         fi
9137                         # only print alsa on last line if short enough, otherwise print on its own line
9138                         if [[ $i -eq 0 ]];then
9139                                 if [[ -n $alsa_data && $( calculate_line_length "$card_string${audio_data}$alsa_data" ) -lt $COLS_INNER ]];then
9140                                         audio_data="$audio_data$alsa_data"
9141                                         alsa_data=''
9142                                 fi
9143                         fi
9144                         if [[ -n $audio_data ]];then
9145                                 if [[ $( calculate_line_length "$card_string$audio_data" ) -lt $COLS_INNER ]];then
9146                                         print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
9147                                         print_screen_output "$print_data"
9148                                 # print the line
9149                                 else
9150                                         # keep the driver on the same line no matter what, looks weird alone on its own line
9151                                         if [[ $B_EXTRA_DATA != 'true' ]];then
9152                                                 print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
9153                                                 print_screen_output "$print_data"
9154                                         else
9155                                                 print_data=$( create_print_line "$line_starter" "$card_string" )
9156                                                 print_screen_output "$print_data"
9157                                                 line_starter=' '
9158                                                 print_data=$( create_print_line "$line_starter" "$audio_data" )
9159                                                 print_screen_output "$print_data"
9160                                         fi
9161                                 fi
9162                                 line_starter=' '
9163                         fi
9164                 done
9165         fi
9166         if [[ -n $alsa_data ]];then
9167                 alsa_data=$( sed 's/ALSA/Advanced Linux Sound Architecture/' <<< $alsa_data )
9168                 alsa_data=$( create_print_line "$line_starter" "$alsa_data" )
9169                 print_screen_output "$alsa_data"
9170         fi
9171         eval $LOGFE
9172 }
9173
9174 print_cpu_data()
9175 {
9176         eval $LOGFS
9177         local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data=''
9178         local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' flag_feature='flags'
9179         local a_cpu_working='' cpu_model='' cpu_clock='' cpu_null_error=''
9180         local cpc_plural='' cpu_count_print='' model_plural='' cpu_data_string=''
9181         local cpu_physical_count='' cpu_core_count='' cpu_core_alpha='' cpu_type=''
9182         local cpu_2_data='' line_starter=''
9183
9184         ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\""
9185         # Array A_CPU_DATA always has one extra element: max clockfreq found.
9186         # that's why its count is one more than you'd think from cores/cpus alone
9187         # load A_CPU_DATA
9188         get_cpu_data
9189
9190         IFS=","
9191         a_cpu_working=(${A_CPU_DATA[0]})
9192         IFS="$ORIGINAL_IFS"
9193
9194         # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1
9195         # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>"
9196         # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_,
9197         # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note.
9198         # This has been confirmed by #bash on freenode.
9199         # The above mentioned only emerges when using the debugging markers below
9200         ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------"
9201         # unless all these are null, process whatever you have
9202         if [[ -n ${a_cpu_working[0]} || -n ${a_cpu_working[1]} || -n ${a_cpu_working[2]} || -n ${a_cpu_working[3]} ]];then
9203                 cpu_model="${a_cpu_working[0]}"
9204                 ## assemble data for output
9205                 cpu_clock="${a_cpu_working[1]}"
9206
9207                 cpu_vendor=${a_cpu_working[5]}
9208
9209                 # set A_CPU_CORE_DATA
9210                 get_cpu_core_count
9211                 cpu_physical_count=${A_CPU_CORE_DATA[0]}
9212                 cpu_core_count=${A_CPU_CORE_DATA[3]}
9213                 cpu_core_alpha=${A_CPU_CORE_DATA[1]}
9214                 cpu_type=${A_CPU_CORE_DATA[2]}
9215                 
9216                 if [[ $cpu_physical_count -gt 1 ]];then
9217                         cpc_plural='(s)'
9218                         cpu_count_print="$cpu_physical_count "
9219                         model_plural='s'
9220                 fi
9221                 line_starter="CPU$cpc_plural:"
9222                 cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
9223                 cpu_data="${C1}${cpu_data_string}${C2} ${a_cpu_working[0]}$model_plural (${cpu_type})"
9224                 if [[ $B_SHOW_CPU == 'true' ]];then
9225                         # update for multicore, bogomips x core count.
9226                         if [[ $B_EXTRA_DATA == 'true' ]];then
9227         #                       if [[ $cpu_vendor != 'intel' ]];then
9228                                 # ARM may use the faked 1 cpucorecount to make this work
9229                                 # echo $cpu_core_count $cpu_physical_count
9230                                 if [[ -n ${a_cpu_working[4]} ]];then
9231                                         bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
9232                                         bmip_data=${bmip_data%.*}
9233                                 fi
9234         #                       else
9235         #                               bmip_data="${a_cpu_working[4]}"
9236         #                       fi
9237                                 # bogomips are a linux thing, but my guess is over time bsds will use them somewhere anyway
9238                                 if [[ $BSD_TYPE == 'bsd' && -z $bmip_data ]];then
9239                                         bmip_data=''
9240                                 else
9241                                         bmip_data="${C1}bmips$SEP3${C2} $bmip_data "
9242                                 fi
9243                         fi
9244                         ## note: this handles how intel reports L2, total instead of per core like AMD does
9245                         # note that we need to multiply by number of actual cpus here to get true cache size
9246                         if [[ -n ${a_cpu_working[2]} ]];then
9247                                 if [[ $cpu_vendor != 'intel' ]];then
9248                                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))"  )
9249                                 else
9250                                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count"  )
9251                                 fi
9252                         else
9253                                 cpu_cache='N/A'
9254                         fi
9255                         # only print shortened list
9256                         if [[ $B_CPU_FLAGS_FULL != 'true' ]];then
9257                                 # gawk has already sorted this output, no flags returns -
9258                                 if [[ $B_EXTRA_DATA == 'true' ]];then
9259                                         cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" "${a_cpu_working[6]}" )
9260                                         cpu_flags="($cpu_flags)"
9261                                         if [[ ${a_cpu_working[6]} == 'true' ]];then
9262                                                 flag_feature='features'
9263                                         fi
9264                                         
9265                                         cpu_flags="${C1}$flag_feature$SEP3${C2} $cpu_flags "
9266                                 fi
9267                         fi
9268                         # arm cpus do not have flags or cache
9269                         if [[ ${a_cpu_working[6]} != 'true' ]];then
9270                                 cpu_data="$cpu_data${C2} ${C1}cache$SEP3${C2} $cpu_cache${CN}"
9271                                 cpu_2_data="$cpu_flags$bmip_data${CN}"
9272                         else
9273                                 cpu_data="$cpu_data${C2} (ARM)$bmip_data${CN}"
9274                         fi
9275                 fi
9276                 # we don't this printing out extra line unless > 1 cpu core
9277                 if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
9278                         cpu_clock_speed='' # null < verbosity level 5
9279                 else
9280                         cpu_data="$cpu_data ${C1}clocked at${C2} ${a_cpu_working[1]%.*} MHz${CN}"
9281                 fi
9282                 cpu_2_data="$cpu_2_data$cpu_clock_speed"
9283         else
9284                 if [[ $BSD_TYPE == 'bsd' && $B_ROOT != 'true' ]];then
9285                         cpu_null_error=' No permissions for sysctl use?'
9286                 fi
9287                 cpu_data="${C2}No CPU data available.$cpu_null_error"
9288         fi
9289 #       echo $cpu_data $cpu_2_data
9290 #       echo ln: $( calculate_line_length "$cpu_data $cpu_2_data" )
9291 #       echo cpl: $( create_print_line "$line_starter" "${cpu_2_data}" ):
9292 #       echo icols: $COLS_INNER
9293 #       echo tc: $TERM_COLUMNS
9294         # echo :${cpu_2_data}:
9295         if [[ -n $cpu_2_data && $( calculate_line_length "$cpu_data $cpu_2_data" ) -gt $COLS_INNER ]];then
9296                 cpu_data=$( create_print_line "$line_starter" "${cpu_data}" )
9297                 line_starter=''
9298                 print_screen_output "$cpu_data"
9299                 cpu_data=$( create_print_line " " "${cpu_2_data}" )
9300                 print_screen_output "$cpu_data"
9301         else
9302                 cpu_data=$( create_print_line "$line_starter" "${cpu_data}" )
9303                 print_screen_output "$cpu_data ${cpu_2_data}"
9304         fi
9305         # we don't this printing out extra line unless > 1 cpu core
9306         # note the numbering, the last array item is the min/max/not found for cpu speeds
9307         if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
9308                 for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ ))
9309                 do
9310                         IFS=","
9311                         a_cpu_working=(${A_CPU_DATA[i]})
9312                         IFS="$ORIGINAL_IFS"
9313                         # note: the first iteration will create a first space, for color code separation below
9314                         cpu_multi_clock_data="$cpu_multi_clock_data ${C1}$(( i + 1 )):${C2} ${a_cpu_working[1]%.*} MHz${CN}"
9315                         # someone actually appeared with a 16 core system, so going to stop the cpu core throttle
9316                         # if this had some other purpose which we can't remember we'll add it back in
9317                         #if [[ $i -gt 10 ]];then
9318                         #       break
9319                         #fi
9320                 done
9321                 if [[ -n $cpu_multi_clock_data ]];then
9322                         cpu_multi_clock_data=$( create_print_line " " "${C1}Clock Speeds:${C2}$cpu_multi_clock_data" )
9323                         print_screen_output "$cpu_multi_clock_data"
9324                 fi
9325         fi
9326         if [[ $B_CPU_FLAGS_FULL == 'true' ]];then
9327                 print_cpu_flags_full "${a_cpu_working[3]}" "${a_cpu_working[6]}"
9328         fi
9329         eval $LOGFE
9330 }
9331
9332 # takes list of all flags, split them and prints x per line
9333 # args: $1 - cpu flag string; $2 - arm true/false
9334 print_cpu_flags_full()
9335 {
9336         eval $LOGFS
9337         # note: sort only sorts lines, not words in a string, so convert to lines
9338         local cpu_flags_full="$( echo $1 | tr " " "\n" | sort )" 
9339         local a_cpu_flags='' line_starter='' temp_string=''
9340         local i=0 counter=0 starter_length=15 flag='' flag_data=''
9341         local line_length='' flag_feature='Flags' spacer='' flag_string=''
9342         
9343         if [[ $2 == 'true' ]];then
9344                 flag_feature='Features'
9345         fi
9346         line_starter="CPU $flag_feature$SEP3"
9347         starter_length=$(( ${#line_starter} + 1 ))
9348         line_starter="${C1}$line_starter${C2} "
9349         line_length=$(( $COLS_INNER - $starter_length ))
9350         # build the flag line array
9351         for flag in $cpu_flags_full
9352         do
9353                 temp_string="$flag_string$spacer$flag"
9354                 spacer=' '
9355                 # handle inner line starter
9356                 if [[ $counter -gt 0 ]];then
9357                         line_length=$COLS_INNER
9358                 fi
9359                 if [[ $line_length -ge ${#temp_string} ]];then
9360                         flag_string=$temp_string
9361                 else
9362                         a_cpu_flags[$counter]=$flag_string
9363                         flag_string=$flag
9364                         (( counter++ ))
9365                 fi
9366                 temp_string=''
9367         done
9368         if [[ -n $flag_string ]];then
9369                 a_cpu_flags[$counter]=$flag_string
9370         fi
9371         # then print it out
9372         for (( i=0; i < ${#a_cpu_flags[@]};i++ ))
9373         do
9374                 if [[ $i -gt 0 ]];then
9375                         line_starter=''
9376                 fi
9377                 flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" )
9378                 print_screen_output "$flag_data"
9379         done
9380         eval $LOGFE
9381 }
9382
9383 print_graphics_data()
9384 {
9385         eval $LOGFS
9386         local graphics_data='' card_id='' i='' root_alert='' root_x_string='' a_graphics_working=''
9387         local b_is_mesa='false' display_full_string='' card_bus_id='' card_data=''
9388         local res_tty='Resolution' xorg_data='' display_vendor_string='' chip_id=''
9389         local spacer='' driver='' driver_string='' driver_plural='' direct_render_string=''
9390         local separator_loaded='' separator_unloaded='' separator_failed='' 
9391         local loaded='' unloaded='' failed='' display_server_string=''
9392         local line_starter='Graphics:'
9393         local screen_resolution="$( get_graphics_res_data )"
9394         
9395         # set A_DISPLAY_SERVER_DATA
9396         get_graphics_display_server_data
9397         local display_vendor=${A_DISPLAY_SERVER_DATA[0]}
9398         local display_version=${A_DISPLAY_SERVER_DATA[1]}
9399         # set A_GLX_DATA
9400         get_graphics_glx_data
9401         local glx_renderer="${A_GLX_DATA[0]}"
9402         local glx_version="${A_GLX_DATA[1]}"
9403         # this can contain a long No case debugging message, so it's being sliced off
9404         # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why
9405         local glx_direct_render=$( gawk '{print $1}' <<< "${A_GLX_DATA[2]}" )
9406
9407         # set A_GRAPHICS_CARD_DATA
9408         if [[ $BSD_TYPE == 'bsd' ]];then
9409                 if [[ $B_PCICONF_SET == 'false' ]];then
9410                         get_pciconf_data
9411                 fi
9412                 get_pciconf_card_data 'display'
9413         else
9414                 get_graphics_card_data
9415         fi
9416         # set A_GRAPHIC_DRIVERS
9417         get_graphics_driver
9418         
9419         if [[ ${#A_GRAPHIC_DRIVERS[@]} -eq 0 ]];then
9420                 driver=' N/A'
9421         else
9422                 for (( i=0; i < ${#A_GRAPHIC_DRIVERS[@]}; i++ ))
9423                 do
9424                         IFS=","
9425                         a_graphics_working=( ${A_GRAPHIC_DRIVERS[i]} )
9426                         IFS="$ORIGINAL_IFS"
9427                         case ${a_graphics_working[1]} in
9428                                 loaded)
9429                                         loaded="$loaded$separator_loaded${a_graphics_working[0]}"
9430                                         separator_loaded=','
9431                                         ;;
9432                                 unloaded)
9433                                         unloaded="$unloaded$separator_unloaded${a_graphics_working[0]}"
9434                                         separator_unloaded=','
9435                                         ;;
9436                                 failed)
9437                                         failed="$failed$separator_failed${a_graphics_working[0]}"
9438                                         separator_failed=','
9439                                         ;;              
9440                         esac
9441                 done
9442         fi
9443         if [[ -n $loaded ]];then
9444                 driver="${driver} $loaded"
9445         fi
9446         if [[ -n $unloaded ]];then
9447                 driver="${driver} (unloaded: $unloaded)"
9448         fi
9449         if [[ -n $failed ]];then
9450                 driver="${driver} ${RED}FAILED:${C2} $failed"
9451         fi
9452         # sometimes for some reason there is no driver found but the array is started
9453         if [[ -z $driver ]];then
9454                 driver=' N/A'
9455         fi
9456
9457         if [[ ${#A_GRAPHIC_DRIVERS[@]} -gt 1 ]];then
9458                 driver_plural='s'
9459         fi
9460         driver_string="${C1}driver$driver_plural$SEP3${C2}$driver "
9461         
9462         # some basic error handling:
9463         if [[ -z $screen_resolution ]];then
9464                 screen_resolution='N/A'
9465         fi
9466         if [[ -z $display_vendor || -z $display_version ]];then
9467                 display_vendor_string="N/A"
9468         else
9469                 display_vendor_string="$display_vendor $display_version"
9470         fi
9471         display_server_string="${C1}Display Server${SEP3}${C2} $display_vendor_string "
9472
9473         if [[ $B_ROOT == 'true' ]];then
9474                 root_x_string='for root '
9475                 if [[ $B_RUNNING_IN_SHELL == 'true' || $B_CONSOLE_IRC == 'true' ]];then
9476                         res_tty='tty size'
9477                 fi
9478         fi
9479         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
9480                 root_x_string="${root_x_string}out of X"
9481                 res_tty='tty size'
9482         fi
9483         
9484         if [[ -n $root_x_string ]];then
9485                 root_x_string="${C1}Advanced Data:${C2} N/A $root_x_string"
9486         fi
9487
9488         display_full_string="$display_server_string$driver_string${C1}${res_tty}$SEP3${C2} ${screen_resolution} $root_x_string"
9489
9490         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 0 ]];then
9491                 for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
9492                 do
9493                         IFS=","
9494                         a_graphics_working=( ${A_GRAPHICS_CARD_DATA[i]} )
9495                         IFS="$ORIGINAL_IFS"
9496                         card_bus_id=''
9497                         card_data=${a_graphics_working[0]}
9498                         if [[ $B_EXTRA_DATA == 'true' ]];then
9499                                 if [[ -n ${a_graphics_working[1]} ]];then
9500                                         card_bus_id=" ${C1}bus-ID$SEP3${C2} ${a_graphics_working[1]}"
9501                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9502                                                 if [[ $BSD_TYPE != 'bsd' ]];then
9503                                                         chip_id=$( get_lspci_chip_id "${a_graphics_working[1]}" )
9504                                                 else
9505                                                         chip_id=${a_graphics_working[2]}
9506                                                 fi
9507                                         fi
9508                                 else
9509                                         card_bus_id=" ${C1}bus-ID$SEP3${C2} N/A"
9510                                 fi
9511                         fi
9512                         if [[ -n $chip_id ]];then
9513                                 chip_id=" ${C1}chip-ID$SEP3${C2} $chip_id"
9514                         fi
9515                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
9516                                 card_id="Card-$(($i+1)):"
9517                         else
9518                                 card_id='Card:'
9519                         fi
9520                         graphics_data="${C1}$card_id${C2} $card_data$card_bus_id$chip_id "
9521                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
9522                                 graphics_data=$( create_print_line "$line_starter" "${graphics_data}" )
9523                                 print_screen_output "$graphics_data"
9524                                 line_starter=' '
9525                                 graphics_data=''
9526                         fi
9527                 done
9528         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
9529         else
9530                 graphics_data="${C1}Card:${C2} Failed to Detect Video Card! "
9531         fi
9532         if [[ -n $graphics_data && $( calculate_line_length "${graphics_data}$display_full_string" ) -lt $COLS_INNER ]];then
9533                 graphics_data=$( create_print_line "$line_starter" "${graphics_data}$display_full_string" )
9534         else
9535                 if [[ -n $graphics_data ]];then
9536                         graphics_data=$( create_print_line "$line_starter" "$graphics_data" )
9537                         print_screen_output "$graphics_data"
9538                         line_starter=' '
9539                 fi
9540                 graphics_data=$( create_print_line "$line_starter" "$display_full_string" )
9541         fi
9542         print_screen_output "$graphics_data"
9543         # if [[ -z $glx_renderer || -z $glx_version ]];then
9544         #       b_is_mesa='true'
9545         # fi
9546
9547         ## note: if glx render or display_version have no content, then mesa is true
9548         # if [[ $B_SHOW_DISPLAY_DATA == 'true' ]] && [[ $b_is_mesa != 'true' ]];then
9549         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
9550                 if [[ -z $glx_renderer ]];then
9551                         glx_renderer='N/A'
9552                 fi
9553                 if [[ -z $glx_version ]];then
9554                         glx_version='N/A'
9555                 fi
9556                 if [[ -z $glx_direct_render ]];then
9557                         glx_direct_render='N/A'
9558                 fi
9559                 if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then
9560                         direct_render_string=" ${C1}Direct Rendering$SEP3${C2} ${glx_direct_render}${CN}"
9561                 fi
9562                 graphics_data="${C1}GLX Renderer$SEP3${C2} ${glx_renderer} ${C1}GLX Version$SEP3${C2} ${glx_version}${CN}$direct_render_string"
9563                 graphics_data=$( create_print_line " " "$graphics_data" )
9564                 
9565                 print_screen_output "$graphics_data"
9566         fi
9567         eval $LOGFE
9568 }
9569
9570 print_hard_disk_data()
9571 {
9572         eval $LOGFS
9573         local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string=''
9574         local hdd_serial=''
9575         local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name='' divisor=5
9576         local Line_Starter='Drives:' # inherited by print_optical_drives
9577
9578         # load A_HDD_DATA
9579         get_hdd_data_basic
9580         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
9581         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
9582         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
9583         IFS=","
9584         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
9585         IFS="$ORIGINAL_IFS"
9586         local hdd_capacity="${a_hdd_basic_working[0]}"
9587         local hdd_used=${a_hdd_basic_working[1]}
9588         local bsd_unsupported='Hard drive data not yet supported for BSD systems.'
9589         local hdd_name_temp=''
9590
9591         if [[ $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
9592         ## note: the output part of this should be in the print hdd data function, not here
9593                 get_hard_drive_data_advanced
9594                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
9595                 do
9596                         # this adds the (x) numbering in front of each disk found, and creates the full disk string
9597                         IFS=","
9598                         a_hdd_working=( ${A_HDD_DATA[i]} )
9599                         IFS="$ORIGINAL_IFS"
9600                         if [[ $B_SHOW_DISK == 'true' ]];then
9601                                 if [[ -n ${a_hdd_working[3]} ]];then
9602                                         usb_data="${a_hdd_working[3]} "
9603                                 else
9604                                         usb_data=''
9605                                 fi
9606                                 dev_data="/dev/${a_hdd_working[0]} "
9607                                 size_data=" ${C1}size$SEP3${C2} ${a_hdd_working[1]}"
9608                                 if [[ $B_EXTRA_DATA == 'true' && -n $dev_data ]];then
9609                                         hdd_temp_data=$( get_hdd_temp_data "$dev_data" )
9610                                         # error handling is done in get data function
9611                                         if [[ -n $hdd_temp_data ]];then
9612                                                 hdd_temp_data=" ${C1}temp$SEP3${C2} ${hdd_temp_data}C"
9613                                         else
9614                                                 hdd_temp_data=''
9615                                         fi
9616                                 fi
9617                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9618                                         hdd_serial=$( get_hdd_serial_number "${a_hdd_working[0]}" )
9619                                         if [[ -z $hdd_serial ]];then
9620                                                 hdd_serial='N/A'
9621                                         fi
9622                                         hdd_serial=" ${C1}serial$SEP3${C2} $hdd_serial"
9623                                         divisor=1 # print every line
9624                                 else
9625                                         divisor=2 # for modulus line print out, either 2 items for full, or default for short
9626                                 fi
9627                                 dev_data="${C1}id$SEP3${C2} /dev/${a_hdd_working[0]} "
9628                         fi
9629                         if [[ -n ${a_hdd_working[2]} ]];then
9630                                 hdd_name_temp=${a_hdd_working[2]}
9631                         else
9632                                 hdd_name_temp='N/A'
9633                         fi
9634                         hdd_name="${C1}model$SEP3${C2} $hdd_name_temp"
9635                         hdd_string="$usb_data$dev_data$hdd_name$size_data$hdd_serial$hdd_temp_data"
9636                         hdd_model="${hdd_model}${C1}$(($i+1)):${C2} $hdd_string "
9637                         # printing line one, then new lines according to $divisor setting, and after, if leftovers, print that line.
9638                         case $i in 
9639                                 0)
9640                                         if [[ $divisor -eq 1 ]];then
9641                                                 hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})" )
9642                                                 print_screen_output "$hdd_data"
9643                                                 Line_Starter=' '
9644                                                 hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}" )
9645                                                 print_screen_output "$hdd_data"
9646                                                 hdd_model=''
9647                                         else
9648                                                 hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used}) ${hdd_model}" )
9649                                                 print_screen_output "$hdd_data"
9650                                                 hdd_model=''
9651                                                 Line_Starter=' '
9652                                         fi
9653                                         ;;
9654                                 *)
9655                                         # using modulus here, if divisible by $divisor, print line, otherwise skip
9656                                         if [[ $(( $i % $divisor )) -eq 0 ]];then
9657                                                 hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
9658                                                 print_screen_output "$hdd_data"
9659                                                 hdd_model=''
9660                                                 Line_Starter=' '
9661                                         fi
9662                                         ;;
9663                         esac
9664                 done
9665                 # then print any leftover items
9666                 if [[ -n $hdd_model ]];then
9667                         hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
9668                         print_screen_output "$hdd_data"
9669                 fi
9670                 # temporary message to indicate not yet supported
9671                 if [[ $BSD_TYPE == 'bsd' ]];then
9672                         hdd_data=$bsd_unsupported
9673                         hdd_data=$( create_print_line "$Line_Starter" "$hdd_data${CN}" )
9674                         print_screen_output "$hdd_data"
9675                         Line_Starter=' '
9676                 fi
9677         else
9678                 # temporary message to indicate not yet supported
9679                 hdd_data="${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})"
9680                 if [[ $BSD_TYPE == 'bsd' ]];then
9681                         hdd_data=$bsd_unsupported
9682                 fi
9683                 hdd_data=$( create_print_line "$Line_Starter" "$hdd_data${CN}" )
9684                 print_screen_output "$hdd_data"
9685                 Line_Starter=' '
9686         fi
9687         if [[ $B_SHOW_FULL_OPTICAL == 'true' || $B_SHOW_BASIC_OPTICAL == 'true' ]];then
9688                 print_optical_drive_data
9689         fi
9690
9691         eval $LOGFE
9692 }
9693
9694 print_info_data()
9695 {
9696         eval $LOGFS
9697
9698         local info_data='' line_starter='Info:' runlvl_default='' runlvl='' runlvl_title='runlevel' 
9699         local init_data='' init_type='' init_version='' rc_type='' rc_version=''
9700         local client_data='' shell_data='' shell_parent='' tty_session=''
9701         local memory="$( get_memory_data )"
9702         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
9703         local up_time="$( get_uptime )"
9704         local patch_version_number=$( get_patch_version_string )
9705         local gcc_string='' gcc_installed='' gcc_others='' closing_data='' 
9706         
9707         if [[ -z $memory ]];then
9708                 memory='N/A'
9709         fi
9710         
9711         if [[ $B_EXTRA_DATA == 'true' ]];then
9712                 get_gcc_system_version
9713                 if [[ ${#A_GCC_VERSIONS[@]} -gt 0 ]];then
9714                         if [[ -n ${A_GCC_VERSIONS[0]} ]];then
9715                                 gcc_installed=${A_GCC_VERSIONS[0]}
9716                         else
9717                                 gcc_installed='N/A'
9718                         fi
9719                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_GCC_VERSIONS[1]} ]];then
9720                                 gcc_others=" ${C1}alt$SEP3${C2} $( tr ',' '/' <<< ${A_GCC_VERSIONS[1]} )"
9721                         fi
9722                         gcc_installed="${C1}Gcc sys$SEP3${C2} $gcc_installed$gcc_others "
9723                 fi
9724         fi
9725         if [[  $B_RUNNING_IN_SHELL == 'true' ]];then
9726                 shell_data=$( get_shell_data )
9727                 if [[ -n $shell_data ]];then
9728                         # note, if you start this in tty, it will give 'login' as the parent, which we don't want.
9729                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9730                                 if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
9731                                         shell_parent=$( get_tty_number )
9732                                         shell_parent="tty $shell_parent"
9733                                 else
9734                                         shell_parent=$( get_shell_parent )
9735                                 fi
9736                                 if [[ $shell_parent == 'login' ]];then
9737                                         shell_parent=''
9738                                 elif [[ -n $shell_parent ]];then
9739                                         shell_parent=" running in $shell_parent"
9740                                 fi
9741                         fi
9742                         IRC_CLIENT="$IRC_CLIENT ($shell_data$shell_parent)"
9743                 fi
9744         fi
9745
9746         # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch!
9747         # long_last=$( echo -ne "${C1}Processes$SEP3${C2} ${processes}${CN} | ${C1}Uptime$SEP3${C2} ${up_time}${CN} | ${C1}Memory$SEP3${C2} ${MEM}${CN}" )
9748         info_data="${C1}Processes$SEP3${C2} ${processes} ${C1}Uptime$SEP3${C2} ${up_time} ${C1}Memory$SEP3${C2} ${memory}${CN} "
9749
9750         # this only triggers if no X data is present or if extra data switch is on
9751         if [[ $B_SHOW_DISPLAY_DATA != 'true' || $B_EXTRA_DATA == 'true' ]];then
9752                 get_init_data
9753                 if [[ ${A_INIT_DATA[0]} == 'systemd' && -z $( grep -E '^[0-9]$' <<< ${A_INIT_DATA[4]} ) ]];then
9754                         runlvl_title='target'
9755                 fi
9756                 init_type=${A_INIT_DATA[0]}
9757                 if [[ -z $init_type ]];then
9758                         init_type='N/A'
9759                 fi
9760                 
9761                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9762                         init_version=${A_INIT_DATA[1]}
9763                         if [[ -z $init_version ]];then
9764                                 init_version='N/A'
9765                         fi
9766                         init_version=" ${C1}v$SEP3${C2} $init_version"
9767                         rc_version=${A_INIT_DATA[3]}
9768                         if [[ -n $rc_version ]];then
9769                                 rc_version=" ${C1}v$SEP3${C2} $rc_version"
9770                         fi
9771                         
9772                         runlvl_default=${A_INIT_DATA[5]}
9773                 fi
9774                 # currently only using openrc here, otherwise show nothing
9775                 rc_type=${A_INIT_DATA[2]}
9776                 if [[ -n $rc_type ]];then
9777                         rc_type=" ${C1}rc$SEP3${C2} $rc_type$rc_version"
9778                 fi
9779                 init_type="${C1}Init$SEP3${C2} $init_type$init_version "
9780                 
9781                 runlvl=${A_INIT_DATA[4]}
9782                 if [[ -n $runlvl ]];then
9783                         runlvl="${C1}$runlvl_title$SEP3${C2} $runlvl "
9784                 fi
9785                 if [[ -n $runlvl_default ]];then
9786                         runlvl_default="${C1}default$SEP3${C2} $runlvl_default "
9787                 fi
9788                 init_data="$init_type$rc_type$runlvl$runlvl_default"
9789         fi
9790         if [[ $SHOW_IRC -gt 0 ]];then
9791                 client_data="${C1}Client$SEP3${C2} ${IRC_CLIENT}${IRC_CLIENT_VERSION} "
9792         fi
9793         info_data="${info_data}"
9794         closing_data="$client_data${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number${CN}"
9795         
9796         # sometimes gcc is very long, and default runlevel can be long with systemd, so create a gcc-less line first
9797         if [[ $( calculate_line_length "${info_data}${init_data}${gcc_installed}${closing_data}" ) -gt $COLS_INNER ]];then
9798                 info_data=${info_data}${init_data}
9799                 info_data=$( create_print_line "$line_starter" "$info_data" )
9800                 print_screen_output "$info_data"
9801                 init_data=''
9802                 info_data=''
9803                 # closing_data=''
9804                 line_starter=' '
9805                 #echo 1
9806         fi
9807         if [[ $( calculate_line_length "${info_data}${init_data}${gcc_installed}${closing_data}" ) -gt $COLS_INNER ]];then
9808                 info_data=${info_data}${init_data}${gcc_installed}
9809                 info_data=$( create_print_line "$line_starter" "$info_data" )
9810                 print_screen_output "$info_data"
9811                 info_data=''
9812                 gcc_installed=''
9813                 init_data=''
9814                 line_starter=' '
9815                 #echo 2
9816         fi
9817         info_data="${info_data}${init_data}${gcc_installed}${closing_data}"
9818         
9819         info_data=$( create_print_line "$line_starter" "$info_data" )
9820         if [[ $SCHEME -gt 0 ]];then
9821                 info_data="${info_data} ${NORMAL}"
9822         fi
9823         print_screen_output "$info_data"
9824         
9825         eval $LOGFE
9826 }
9827
9828 print_machine_data()
9829 {
9830         eval $LOGFS
9831         
9832         local system_line='' mobo_line='' bios_line='' chassis_line=''
9833         local mobo_vendor='' mobo_model='' mobo_version='' mobo_serial=''
9834         local bios_vendor='' bios_version='' bios_date='' bios_rom=''
9835         local system_vendor='' product_name='' product_version='' product_serial='' product_uuid=''
9836         local chassis_vendor='' chassis_type='' chassis_version='' chassis_serial='' 
9837         local b_skip_system='false' b_skip_chassis='false'
9838         local sysDmiError='No /sys/class/dmi, using '
9839         local sysDmiNull='No /sys/class/dmi machine data: try newer kernel, or install dmidecode'
9840         # set A_MACHINE_DATA
9841         get_machine_data
9842         
9843         if [[ -n $BSD_TYPE ]];then
9844                 sysDmiError=''
9845                 sysDmiNull='No machine data available. Is dmidecode installed?'
9846         fi
9847
9848         IFS=','
9849         ## keys for machine data are:
9850         # 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid 
9851         # 5-board_vendor 6-board_name 7-board_version 8-board_serial 
9852         # 9-bios_vendor 10-bios_version 11-bios_date 
9853         ## with extra data: 
9854         # 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial
9855         
9856         if [[ ${#A_MACHINE_DATA[@]} -gt 0 ]];then
9857                 # note: in some case a mobo/version will match a product name/version, do not print those
9858                 # but for laptops, or even falsely id'ed desktops with batteries, let's print it all if it matches
9859                 # there can be false id laptops if battery appears so need to make sure system is filled
9860                 if [[ -z ${A_MACHINE_DATA[0]} ]];then
9861                         b_skip_system='true'
9862                 else
9863                         if [[ $B_PORTABLE != 'true'  ]];then
9864                                 # ibm / ibm can be true; dell / quantum is false, so in other words, only do this
9865                                 # in case where the vendor is the same and the version is the same and not null, 
9866                                 # otherwise the version information is going to be different in all cases I think
9867                                 if [[ -n ${A_MACHINE_DATA[0]} && ${A_MACHINE_DATA[0]} == ${A_MACHINE_DATA[5]} ]];then
9868                                         if [[ -n ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[2]} == ${A_MACHINE_DATA[7]} ]] || \
9869                                         [[ -z ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[1]} == ${A_MACHINE_DATA[6]} ]];then
9870                                                 b_skip_system='true'
9871                                         fi
9872                                 fi
9873                         fi
9874                 fi
9875                 # no point in showing chassis if system isn't there, it's very unlikely that would be correct
9876                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && $b_skip_system != 'true' ]];then
9877                         if [[ -n ${A_MACHINE_DATA[7]} && ${A_MACHINE_DATA[14]} == ${A_MACHINE_DATA[7]} ]];then
9878                                 b_skip_chassis='true'
9879                         fi
9880                         if [[ -n ${A_MACHINE_DATA[12]} && $b_skip_chassis != 'true' ]];then
9881                                 # no need to print the vendor string again if it's the same
9882                                 if [[ ${A_MACHINE_DATA[12]} != ${A_MACHINE_DATA[0]} ]];then
9883                                         chassis_vendor=" ${A_MACHINE_DATA[12]}"
9884                                 fi
9885                                 if [[ -n ${A_MACHINE_DATA[13]} ]];then
9886                                         chassis_type=" ${C1}type$SEP3${C2} ${A_MACHINE_DATA[13]}"
9887                                 fi
9888                                 if [[ -n ${A_MACHINE_DATA[14]} ]];then
9889                                         chassis_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[14]}"
9890                                 fi
9891                                 if [[ -n ${A_MACHINE_DATA[15]} && $B_OUTPUT_FILTER != 'true' ]];then
9892                                         chassis_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[15]}"
9893                                 fi
9894                                 if [[ -n "$chassis_vendor$chassis_type$chassis_version$chassis_serial" ]];then
9895                                         chassis_line="${C1}Chassis$SEP3${C2}$chassis_vendor$chassis_type$chassis_version$chassis_serial"
9896                                 fi
9897                         fi
9898                 fi
9899                 if [[ -n ${A_MACHINE_DATA[5]} ]];then
9900                         mobo_vendor=${A_MACHINE_DATA[5]}
9901                 else
9902                         mobo_vendor='N/A'
9903                 fi
9904                 if [[ -n ${A_MACHINE_DATA[6]} ]];then
9905                         mobo_model=${A_MACHINE_DATA[6]}
9906                 else
9907                         mobo_model='N/A'
9908                 fi
9909                 if [[ -n ${A_MACHINE_DATA[7]} ]];then
9910                         mobo_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[7]}"
9911                 fi
9912                 if [[ -n ${A_MACHINE_DATA[8]} && $B_OUTPUT_FILTER != 'true' ]];then
9913                         mobo_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[8]}"
9914                 fi
9915                 if [[ -n ${A_MACHINE_DATA[9]} ]];then
9916                         bios_vendor=${A_MACHINE_DATA[9]}
9917                 else
9918                         bios_vendor='N/A'
9919                 fi
9920                 if [[ -n ${A_MACHINE_DATA[10]} ]];then
9921                         bios_version=${A_MACHINE_DATA[10]}
9922                         if [[ -n ${A_MACHINE_DATA[16]} ]];then
9923                                 bios_version="$bios_version rv ${A_MACHINE_DATA[16]}"
9924                         fi
9925                 else
9926                         bios_version='N/A'
9927                 fi
9928                 if [[ -n ${A_MACHINE_DATA[11]} ]];then
9929                         bios_date=${A_MACHINE_DATA[11]}
9930                 else
9931                         bios_date='N/A'
9932                 fi
9933                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_MACHINE_DATA[17]} ]];then
9934                         bios_rom=" ${C1}rom size$SEP3${C2} ${A_MACHINE_DATA[17]}"
9935                 fi
9936                 mobo_line="${C1}Mobo$SEP3${C2} $mobo_vendor ${C1}model$SEP3${C2} $mobo_model$mobo_version$mobo_serial"
9937                 bios_line="${C1}Bios$SEP3${C2} $bios_vendor ${C1}version$SEP3${C2} $bios_version ${C1}date$SEP3${C2} $bios_date$bios_rom"
9938                 if [[ $( calculate_line_length "$mobo_line$bios_line" ) -lt $COLS_INNER ]];then
9939                         mobo_line="$mobo_line $bios_line"
9940                         bios_line=''
9941                 fi
9942                 if [[ $b_skip_system == 'true' ]];then
9943                         system_line=$mobo_line
9944                         mobo_line=''
9945                 else
9946                         # this has already been tested for above so we know it's not null
9947                         system_vendor=${A_MACHINE_DATA[0]}
9948                         if [[ $B_PORTABLE == 'true' ]];then
9949                                 system_vendor="$system_vendor (portable)"
9950                         fi
9951                         if [[ -n ${A_MACHINE_DATA[1]} ]];then
9952                                 product_name=${A_MACHINE_DATA[1]}
9953                         else
9954                                 product_name='N/A'
9955                         fi
9956                         if [[ -n ${A_MACHINE_DATA[2]} ]];then
9957                                 product_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[2]}"
9958                         fi
9959                         if [[ -n ${A_MACHINE_DATA[3]} && $B_OUTPUT_FILTER != 'true' ]];then
9960                                 product_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[3]} "
9961                         fi
9962                         system_line="${C1}System$SEP3${C2} $system_vendor ${C1}product$SEP3${C2} $product_name$product_version$product_serial"
9963                         if [[ -n $chassis_line && $( calculate_line_length "$system_line$chassis_line" ) -lt $COLS_INNER ]];then
9964                                 system_line="$system_line $chassis_line"
9965                                 chassis_line=''
9966                         fi
9967                 fi
9968                 IFS="$ORIGINAL_IFS"
9969         else
9970                 system_line="${C2}$sysDmiNull${CN}"
9971         fi
9972         # patch to dump all of above if dmidecode was data source and non root user
9973         if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' || ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
9974                 if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' ]];then
9975                         system_line="${C2}${sysDmiError}dmidecode: you must be root to run dmidecode${CN}"
9976                 elif [[ ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
9977                         system_line="${C2}${sysDmiError}dmidecode: no machine data available${CN}"
9978                 fi
9979                 mobo_line=''
9980                 bios_line=''
9981                 chassis_line=''
9982         fi
9983         system_line=$( create_print_line "Machine:" "$system_line" )
9984         print_screen_output "$system_line"
9985         if [[ -n $mobo_line ]];then
9986                 mobo_line=$( create_print_line " " "$mobo_line" )
9987                 print_screen_output "$mobo_line"
9988         fi
9989         if [[ -n $bios_line ]];then
9990                 bios_line=$( create_print_line " " "$bios_line" )
9991                 print_screen_output "$bios_line"
9992         fi
9993         if [[ -n $chassis_line ]];then
9994                 chassis_line=$( create_print_line " " "$chassis_line" )
9995                 print_screen_output "$chassis_line"
9996         fi
9997         
9998         eval $LOGFE
9999 }
10000
10001 # args: $1 - module name (could be > 1, so loop it ); $2 - audio (optional)
10002 print_module_version()
10003 {
10004         eval $LOGFS
10005         local module_versions='' module='' version='' prefix='' modules=$1
10006         
10007         # note that sound driver data tends to have upper case, but modules are lower
10008         if [[ $2 == 'audio' ]];then
10009                 if [[ -z $( grep -E '^snd' <<< $modules ) ]];then
10010                         prefix='snd_' # sound modules start with snd_
10011                 fi
10012                 modules=$( tr '[A-Z]' '[a-z]' <<< $modules )
10013                 modules=$( tr '-' '_' <<< $modules )
10014                 # special intel processing, generally no version info though
10015                 if [[ $modules == 'hda intel' ]];then
10016                         modules='hda_intel'
10017                 elif [[ $modules == 'intel ich' ]];then
10018                         modules='intel8x0'
10019                 fi
10020         fi
10021
10022         for module in $modules
10023         do
10024                 version=$( get_module_version_number "$prefix$module" )
10025                 if [[ -n $version ]];then
10026                         module_versions="$module_versions $version"
10027                 fi
10028         done
10029
10030         if [[ -n $module_versions ]];then
10031                 echo " ${C1}ver$SEP3${C2}$module_versions"
10032         fi
10033         eval $LOGFE
10034 }
10035
10036 print_networking_data()
10037 {
10038         eval $LOGFS
10039         local i='' card_id='' network_data='' a_network_working='' port_data='' driver_data=''
10040         local card_string='' port_plural='' module_version='' pci_bus_id='' bus_usb_text=''
10041         local bus_usb_id='' line_starter='Network:' card_string='' card_data='' chip_id=''
10042         local driver=''
10043         # set A_NETWORK_DATA
10044         if [[ $BSD_TYPE == 'bsd' ]];then
10045                 if [[ $B_PCICONF_SET == 'false' ]];then
10046                         get_pciconf_data
10047                 fi
10048                 get_pciconf_card_data 'network'
10049         else
10050                 get_networking_data
10051         fi
10052
10053         # will never be null because null is handled in get_network_data, but in case we change
10054         # that leaving this test in place.
10055         if [[ -n ${A_NETWORK_DATA[@]} ]];then
10056                 for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
10057                 do
10058                         IFS=","
10059                         a_network_working=( ${A_NETWORK_DATA[i]} )
10060                         IFS="$ORIGINAL_IFS"
10061                         bus_usb_id=''
10062                         bus_usb_text=''
10063                         card_data=''
10064                         card_string=''
10065                         driver_data=''
10066                         module_version=''
10067                         network_data=''
10068                         pci_bus_id=''
10069                         port_data=''
10070                         port_plural=''
10071                         card_id=''
10072                         chip_id=''
10073
10074                         if [[ ${#A_NETWORK_DATA[@]} -gt 1 ]];then
10075                                 chip_id="-$(( $i + 1 ))"
10076                         fi
10077                         if [[ -n ${a_network_working[1]} && $B_EXTRA_DATA == 'true' && $BSD_TYPE != 'bsd' ]];then
10078                                 module_version=$( print_module_version "${a_network_working[1]}" )
10079                         fi
10080                         if [[ -n ${a_network_working[1]} ]];then
10081                                 # note: linux drivers can have numbers, like tg3
10082                                 if [[ $BSD_TYPE == 'bsd' ]];then
10083                                         driver=$( sed 's/[0-9]*$//' <<< ${a_network_working[1]} )
10084                                 else
10085                                         driver=${a_network_working[1]}
10086                                 fi
10087                                 driver_data="${C1}driver$SEP3${C2} ${driver}$module_version "
10088                         fi
10089                         if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then
10090                                 if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then
10091                                         port_plural='s'
10092                                 fi
10093                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_network_working[2]} "
10094                         fi
10095                         if [[ -n ${a_network_working[4]} && $B_EXTRA_DATA == 'true' ]];then
10096                                 if [[ -z $( grep '^usb-' <<< ${a_network_working[4]} ) ]];then
10097                                         bus_usb_text='bus-ID'
10098                                         bus_usb_id=${a_network_working[4]}
10099                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10100                                                 if [[ $BSD_TYPE != 'bsd' ]];then
10101                                                         chip_id=$( get_lspci_chip_id "${a_network_working[4]}" )
10102                                                 else
10103                                                         chip_id=${a_network_working[10]}
10104                                                 fi
10105                                         fi
10106                                 else
10107                                         bus_usb_text='usb-ID'
10108                                         bus_usb_id=$( cut -d '-' -f '2-4' <<< ${a_network_working[4]} )
10109                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10110                                                 chip_id=${a_network_working[10]}
10111                                         fi
10112                                 fi
10113                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id"
10114                                 if [[ -n $chip_id ]];then
10115                                         chip_id=" ${C1}chip-ID$SEP3${C2} $chip_id"
10116                                 fi
10117                         fi
10118                         card_string="${C1}Card$card_id:${C2} ${a_network_working[0]} "
10119                         card_data="$driver_data$port_data$pci_bus_id$chip_id"
10120                         if [[ $( calculate_line_length "$card_string$card_data" ) -gt $COLS_INNER ]];then
10121                                 network_data=$( create_print_line "$line_starter" "$card_string" )
10122                                 line_starter=' '
10123                                 card_string=''
10124                                 print_screen_output "$network_data"
10125                         fi
10126                         network_data=$( create_print_line "$line_starter" "$card_string$card_data" )
10127                         line_starter=' '
10128                         print_screen_output "$network_data"
10129                         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' ]];then
10130                                 print_network_advanced_data
10131                         fi
10132                 done
10133         else
10134                 network_data="${C1}Card:${C2} Failed to Detect Network Card! "
10135                 network_data=$( create_print_line "$line_starter" "$network_data" )
10136                 print_screen_output "$network_data"
10137         fi
10138         if [[ $B_SHOW_IP == 'true' ]];then
10139                 print_networking_ip_data
10140         fi
10141         eval $LOGFE
10142 }
10143
10144 print_network_advanced_data()
10145 {
10146         eval $LOGFS
10147         local network_data='' if_id='N/A' duplex='N/A' mac_id='N/A' speed='N/A' oper_state='N/A'
10148         local b_is_wifi='false' speed_string='' duplex_string=''
10149         
10150                 # first check if it's a known wifi id'ed card, if so, no print of duplex/speed
10151         if [[ -n $( grep -Esi '(wireless|wifi|wi-fi|wlan|802\.11|centrino)' <<< ${a_network_working[0]} ) ]];then
10152                 b_is_wifi='true'
10153         fi
10154         if [[ -n ${a_network_working[5]} ]];then
10155                 if_id=${a_network_working[5]}
10156         fi
10157         if [[ -n ${a_network_working[6]} ]];then
10158                 oper_state=${a_network_working[6]}
10159         fi
10160         # no print out for wifi since it doesn't have duplex/speed data availabe
10161         # note that some cards show 'unknown' for state, so only testing explicitly
10162         # for 'down' string in that to skip showing speed/duplex
10163         if [[ $b_is_wifi != 'true' && $oper_state != 'down' ]];then
10164                 if [[ -n ${a_network_working[7]} ]];then
10165                         # make sure the value is strictly numeric before appending Mbps
10166                         if [[ -n $( grep -E '^[0-9\.,]+$' <<< "${a_network_working[7]}" ) ]];then
10167                                 speed="${a_network_working[7]} Mbps"
10168                         else
10169                                 speed=${a_network_working[7]}
10170                         fi
10171                 fi
10172                 speed_string="${C1}speed$SEP3${C2} $speed "
10173                 if [[ -n ${a_network_working[8]} ]];then
10174                         duplex=${a_network_working[8]}
10175                 fi
10176                 duplex_string="${C1}duplex$SEP3${C2} $duplex "
10177         fi
10178         if [[ -n ${a_network_working[9]} ]];then
10179                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10180                         mac_id=$FILTER_STRING
10181                 else
10182                         mac_id=${a_network_working[9]}
10183                 fi
10184         fi
10185         network_data="${C1}IF:${C2} $if_id ${C1}state$SEP3${C2} $oper_state $speed_string$duplex_string${C1}mac$SEP3${C2} $mac_id"
10186         network_data=$( create_print_line " " "$network_data" )
10187         print_screen_output "$network_data"
10188         
10189         eval $LOGFE
10190 }
10191
10192 print_networking_ip_data()
10193 {
10194         eval $LOGFS
10195         local ip=$( get_networking_wan_ip_data )
10196         local wan_ip_data='' a_interfaces_working='' interfaces='' i=''
10197         local if_id='' if_ip='' if_ipv6='' if_ipv6_string='' full_string='' if_string=''
10198         local if_id_string='' if_ip_string=''
10199         local line_max=$(( $COLS_INNER - 40 ))
10200
10201         # set A_INTERFACES_DATA
10202         get_networking_local_ip_data
10203         # first print output for wan ip line. Null is handled in the get function
10204         if [[ -z $ip ]];then
10205                 ip='N/A'
10206         else
10207                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10208                         ip=$FILTER_STRING
10209                 fi
10210         fi
10211         wan_ip_data="${C1}WAN IP:${C2} $ip "
10212         # then create the list of local interface/ip
10213         i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1
10214         while [[ -n ${A_INTERFACES_DATA[i]} ]]
10215         do
10216                 IFS=","
10217                 a_interfaces_working=(${A_INTERFACES_DATA[i]})
10218                 IFS="$ORIGINAL_IFS"
10219                 if_id='N/A'
10220                 if_ip='N/A'
10221                 if_ipv6='N/A'
10222                 if_ipv6_string=''
10223                 if [[ -z $( grep '^Interface' <<< ${a_interfaces_working[0]} ) ]];then
10224                         if [[ -n ${a_interfaces_working[1]} ]];then
10225                                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10226                                         if_ip=$FILTER_STRING
10227                                 else
10228                                         if_ip=${a_interfaces_working[1]}
10229                                 fi
10230                         fi
10231                         if_ip_string=" ${C1}ip$SEP3${C2} $if_ip"
10232                         if [[ $B_EXTRA_DATA == 'true' ]];then
10233                                 if [[ -n ${a_interfaces_working[3]} ]];then
10234                                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
10235                                                 if_ipv6=$FILTER_STRING
10236                                         else
10237                                                 if_ipv6=${a_interfaces_working[3]}
10238                                         fi
10239                                 fi
10240                                 if_ipv6_string=" ${C1}ip-v6$SEP3${C2} $if_ipv6"
10241                         fi
10242                 fi
10243                 if [[ -n ${a_interfaces_working[0]} ]];then
10244                         if_id=${a_interfaces_working[0]}
10245                 fi
10246                 if_string="$wan_ip_data$if_string${C1}IF:${C2} $if_id$if_ip_string$if_ipv6_string "
10247                 wan_ip_data=''
10248                 if [[ $( calculate_line_length "$if_string" ) -gt $line_max ]];then
10249                         full_string=$( create_print_line " " "$if_string" )
10250                         print_screen_output "$full_string"
10251                         if_string=''
10252                 fi
10253                 ((i++))
10254         done
10255         
10256         # then print out anything not printed already
10257         if [[ -n $if_string ]];then
10258                 full_string=$( create_print_line " " "$if_string" )
10259                 print_screen_output "$full_string"
10260         fi
10261         eval $LOGFE
10262 }
10263
10264 print_optical_drive_data()
10265 {
10266         eval $LOGFS
10267         local a_drives='' drive_data='' counter='' 
10268         local drive_id='' drive_links='' vendor='' speed='' multisession='' mcn='' audio=''
10269         local dvd='' state='' rw_support='' rev='' separator='' drive_string=''
10270         get_optical_drive_data
10271         # 0 - true dev path, ie, sr0, hdc
10272         # 1 - dev links to true path
10273         # 2 - device vendor - for hdx drives, vendor model are one string from proc
10274         # 3 - device model
10275         # 4 - device rev version
10276         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 0 ]];then
10277                 for (( i=0; i < ${#A_OPTICAL_DRIVE_DATA[@]}; i++ ))
10278                 do
10279                         IFS=","
10280                         a_drives=(${A_OPTICAL_DRIVE_DATA[i]})
10281                         IFS="$ORIGINAL_IFS"
10282                         audio=''
10283                         drive_data=''
10284                         drive_id=''
10285                         drive_links=''
10286                         dvd='' 
10287                         mcn='' 
10288                         multisession='' 
10289                         rev='' 
10290                         rw_support='' 
10291                         separator=''
10292                         speed='' 
10293                         state='' 
10294                         vendor=''
10295                         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -eq 1 && -z ${a_drives[0]} && -z ${a_drives[1]} ]];then
10296                                 drive_string="No optical drives detected."
10297                                 B_SHOW_FULL_OPTICAL='false'
10298                         else
10299                                 if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 1 ]];then
10300                                         counter="-$(( i + 1 ))"
10301                                 fi
10302                                 if [[ -z ${a_drives[0]} ]];then
10303                                         drive_id='N/A'
10304                                 else
10305                                         drive_id="/dev/${a_drives[0]}"
10306                                 fi
10307                                 drive_links=$( sed 's/~/,/g' <<< ${a_drives[1]} )
10308                                 if [[ -z $drive_links ]];then
10309                                         drive_links='N/A'
10310                                 fi
10311                                 if [[ -n ${a_drives[2]} ]];then
10312                                         vendor=${a_drives[2]}
10313                                         if [[ -n ${a_drives[3]} ]];then
10314                                                 vendor="$vendor ${a_drives[3]}"
10315                                         fi
10316                                 fi
10317                                 if [[ -z $vendor ]];then
10318                                         if [[ -n ${a_drives[3]} ]];then
10319                                                 vendor=${a_drives[3]}
10320                                         else
10321                                                 vendor='N/A'
10322                                         fi
10323                                 fi
10324                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10325                                         if [[ -n ${a_drives[4]} ]];then
10326                                                 rev=${a_drives[4]}
10327                                         else
10328                                                 rev='N/A'
10329                                         fi
10330                                         rev=" ${C1}rev$SEP3${C2} $rev"
10331                                 fi
10332                                 drive_string="$drive_id ${C1}model$SEP3${C2} $vendor$rev ${C1}dev-links$SEP3${C2} $drive_links"
10333                         fi
10334                         drive_data="${C1}Optical${counter}:${C2} $drive_string"
10335                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
10336                         print_screen_output "$drive_data"
10337                         Line_Starter=' '
10338                         # 5 - speed
10339                         # 6 - multisession support
10340                         # 7 - MCN support
10341                         # 8 - audio read
10342                         # 9 - cdr
10343                         # 10 - cdrw
10344                         # 11 - dvd read
10345                         # 12 - dvdr
10346                         # 13 - dvdram
10347                         # 14 - state
10348                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
10349                                 if [[ -z ${a_drives[5]} ]];then
10350                                         speed='N/A'
10351                                 else
10352                                         speed="${a_drives[5]}x"
10353                                 fi
10354                                 if [[ -z ${a_drives[8]} ]];then
10355                                         audio='N/A'
10356                                 elif [[ ${a_drives[8]} == 1 ]];then
10357                                         audio='yes'
10358                                 else
10359                                         audio='no'
10360                                 fi
10361                                 audio=" ${C1}audio$SEP3${C2} $audio"
10362                                 if [[ -z ${a_drives[6]} ]];then
10363                                         multisession='N/A'
10364                                 elif [[ ${a_drives[6]} == 1 ]];then
10365                                         multisession='yes'
10366                                 else
10367                                         multisession='no'
10368                                 fi
10369                                 multisession=" ${C1}multisession$SEP3${C2} $multisession"
10370                                 if [[ -z ${a_drives[11]} ]];then
10371                                         dvd='N/A'
10372                                 elif [[ ${a_drives[11]} == 1 ]];then
10373                                         dvd='yes'
10374                                 else
10375                                         dvd='no'
10376                                 fi
10377                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10378                                         if [[ -z ${a_drives[14]} ]];then
10379                                                 state='N/A'
10380                                         else
10381                                                 state="${a_drives[14]}"
10382                                         fi
10383                                         state=" ${C1}state$SEP3${C2} $state"
10384                                 fi
10385                                 if [[ -n ${a_drives[9]} && ${a_drives[9]} == 1 ]];then
10386                                         rw_support='cd-r'
10387                                         separator=','
10388                                 fi
10389                                 if [[ -n ${a_drives[10]} && ${a_drives[10]} == 1 ]];then
10390                                         rw_support="${rw_support}${separator}cd-rw"
10391                                         separator=','
10392                                 fi
10393                                 if [[ -n ${a_drives[12]} && ${a_drives[12]} == 1 ]];then
10394                                         rw_support="${rw_support}${separator}dvd-r"
10395                                         separator=','
10396                                 fi
10397                                 if [[ -n ${a_drives[13]} && ${a_drives[13]} == 1 ]];then
10398                                         rw_support="${rw_support}${separator}dvd-ram"
10399                                         separator=','
10400                                 fi
10401                                 if [[ -z $rw_support ]];then
10402                                         rw_support='none'
10403                                 fi
10404                                 
10405                                 drive_data="${C1}Features: speed$SEP3${C2} $speed$multisession$audio ${C1}dvd$SEP3${C2} $dvd ${C1}rw$SEP3${C2} $rw_support$state"
10406                                 drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
10407                                 print_screen_output "$drive_data"
10408                         fi
10409                 done
10410         else
10411                 :
10412         fi
10413         eval $LOGFE
10414 }
10415
10416 print_partition_data()
10417 {
10418         eval $LOGFS
10419         local a_partition_working='' partition_used='' partition_data=''
10420         local counter=0 i=0 a_partition_data='' line_starter='' line_max=$(( $COLS_INNER - 25 ))
10421         local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label=''
10422         local part_uuid='' full_uuid='' dev_remote='' full_fs='' line_max_label_uuid=$COLS_INNER
10423         local b_non_dev='false' holder=''
10424
10425         # set A_PARTITION_DATA
10426         get_partition_data
10427
10428         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
10429         do
10430                 IFS=","
10431                 a_partition_working=(${A_PARTITION_DATA[i]})
10432                 IFS="$ORIGINAL_IFS"
10433                 full_label=''
10434                 full_uuid=''
10435
10436                 if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then
10437                         if [[ -n ${a_partition_working[2]} ]];then
10438                                 partition_used="${C1}used$SEP3${C2} ${a_partition_working[2]} (${a_partition_working[3]}) "
10439                         else
10440                                 partition_used='' # reset partition used to null
10441                         fi
10442                         if [[ -n ${a_partition_working[5]} ]];then
10443                                 full_fs="${a_partition_working[5]}"
10444                         else
10445                                 full_fs='N/A' # reset partition fs type
10446                         fi
10447                         full_fs="${C1}fs$SEP3${C2} $full_fs "
10448
10449                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
10450                                 if [[ -n ${a_partition_working[6]} ]];then
10451                                         if [[ -z $( grep -E '(^//|:/|non-dev)' <<< ${a_partition_working[6]} ) ]];then
10452                                                 part_dev="/dev/${a_partition_working[6]}"
10453                                                 dev_remote='dev'
10454                                         elif [[ -n $( grep '^non-dev' <<< ${a_partition_working[6]} ) ]];then
10455                                                 holder=$( sed 's/non-dev-//' <<< ${a_partition_working[6]} )
10456                                                 part_dev="$holder"
10457                                                 dev_remote='raid'
10458                                         else
10459                                                 part_dev="${a_partition_working[6]}"
10460                                                 dev_remote='remote'
10461                                         fi
10462                                 else
10463                                         dev_remote='dev'
10464                                         part_dev='N/A'
10465                                 fi
10466                                 full_dev="${C1}$dev_remote$SEP3${C2} $part_dev "
10467                                 if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then
10468                                         if [[ -n ${a_partition_working[7]} ]];then
10469                                                 part_label="${a_partition_working[7]}"
10470                                         else
10471                                                 part_label='N/A'
10472                                         fi
10473                                         full_label="${C1}label$SEP3${C2} $part_label "
10474                                 fi
10475                                 if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then
10476                                         if [[ -n ${a_partition_working[8]} ]];then
10477                                                 part_uuid="${a_partition_working[8]}"
10478                                         else
10479                                                 part_uuid='N/A'
10480                                         fi
10481                                         full_uuid="${C1}uuid$SEP3${C2} $part_uuid"
10482                                 fi
10483                         fi
10484                         # don't show user names in output
10485                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
10486                                 partitionIdClean=$( sed $SED_RX "s|/home/([^/]+)/(.*)|/home/$FILTER_STRING/\2|" <<< ${a_partition_working[0]} )
10487                         else
10488                                 partitionIdClean=${a_partition_working[0]}
10489                         fi
10490                         id_size_fs="${C1}ID:${C2} $partitionIdClean ${C1}size$SEP3${C2} ${a_partition_working[1]} $partition_used$full_fs$full_dev"
10491                         label_uuid="$full_label$full_uuid"
10492                         # label/uuid always print one per line, so only wrap if it's very long
10493                         if [[ $B_SHOW_UUIDS == 'true' && $B_SHOW_LABELS == 'true' && $( calculate_line_length "$id_size_fs$label_uuid" ) -gt $line_max_label_uuid ]];then
10494                                 a_partition_data[$counter]="$id_size_fs"
10495                                 ((counter++))
10496                                 a_partition_data[$counter]="$label_uuid"
10497                         else
10498                                 a_partition_data[$counter]="${a_partition_data[$counter]}$id_size_fs$label_uuid"
10499                         fi
10500                         # because these lines can vary widely, using dynamic length handling here
10501                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]] || [[ $( calculate_line_length "${a_partition_data[$counter]}" ) -gt $line_max ]];then
10502                                 ((counter++))
10503                         fi
10504                 fi
10505         done
10506         # print out all lines, line starter on first line
10507         for (( i=0; i < ${#a_partition_data[@]};i++ ))
10508         do
10509                 if [[ $i -eq 0 ]];then
10510                         line_starter='Partition:'
10511                 else
10512                         line_starter=' '
10513                 fi
10514                 partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" )
10515                 print_screen_output "$partition_data"
10516         done
10517         
10518         eval $LOGFE
10519 }
10520
10521 print_program_version()
10522 {
10523         local patch_version_number=$( get_patch_version_string )
10524         local program_version="${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number${CN}"
10525         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
10526         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
10527         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
10528         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
10529         #local line_max=$COLS_INNER
10530         #program_version="$( sed -e :a -e "s/^.\{1,$line_max\}$/ &/;ta" <<< $program_version )" # use to create padding if needed
10531         # program_version=$( create_print_line "Version:" "$program_version" )
10532         print_screen_output "$program_version"
10533 }
10534
10535 print_ps_data()
10536 {
10537         eval $LOGFS
10538         
10539         local b_print_first='true' 
10540
10541         if [[ $B_SHOW_PS_CPU_DATA == 'true' ]];then
10542                 get_ps_tcm_data 'cpu'
10543                 print_ps_item 'cpu' "$b_print_first"
10544                 b_print_first='false' 
10545         fi
10546         if [[ $B_SHOW_PS_MEM_DATA == 'true' ]];then
10547                 get_ps_tcm_data 'mem'
10548                 print_ps_item 'mem' "$b_print_first"
10549         fi
10550         
10551         eval $LOGFE
10552 }
10553
10554 # args: $1 - cpu/mem; $2 true/false
10555 print_ps_item()
10556 {
10557         eval $LOGFS
10558         local a_ps_data='' ps_data='' line_starter='' line_start_data='' full_line=''
10559         local app_name='' app_pid='' app_cpu='' app_mem='' throttled='' app_daemon=''
10560         local b_print_first=$2 line_counter=0 i=0 count_nu='' extra_data=''
10561         
10562         if [[ -n $PS_THROTTLED ]];then
10563                 throttled=" ${C1} - throttled from${C2} $PS_THROTTLED"
10564         fi
10565         case $1 in
10566                 cpu)
10567                         line_start_data="${C1}CPU - % used - top ${C2} $PS_COUNT ${C1}active$throttled "
10568                         ;;
10569                 mem)
10570                         line_start_data="${C1}Memory - MB / % used - top ${C2} $PS_COUNT ${C1}active$throttled"
10571                         ;;
10572         esac
10573         
10574         if [[ $b_print_first == 'true' ]];then
10575                 line_starter='Processes:'
10576         else
10577                 line_starter=' '
10578         fi
10579         
10580         # appName, appPath, appStarterName, appStarterPath, cpu, mem, pid, vsz, user
10581         ps_data=$( create_print_line "$line_starter" "$line_start_data" )
10582         print_screen_output "$ps_data"
10583
10584         for (( i=0; i < ${#A_PS_DATA[@]}; i++ ))
10585         do
10586                 IFS=","
10587                 a_ps_data=(${A_PS_DATA[i]})
10588                 IFS="$ORIGINAL_IFS"
10589                 
10590                 # handle the converted app names, with ~..~ means it didn't have a path
10591                 if [[ -n $( grep -E '^~.*~$' <<<  ${a_ps_data[0]} ) ]];then
10592                         app_daemon='daemon'
10593                 else
10594                         app_daemon='command'
10595                 fi
10596
10597                 app_name=" ${C1}$app_daemon$SEP3${C2} ${a_ps_data[0]}"
10598                 if [[ ${a_ps_data[0]} != ${a_ps_data[2]} ]];then
10599                         app_name="$app_name ${C1}(started by$SEP3${C2} ${a_ps_data[2]}${C1})${C2}"
10600                 fi
10601                 app_pid=" ${C1}pid$SEP3${C2} ${a_ps_data[6]}"
10602                 #  ${C1}user:${C2} ${a_ps_data[8]}
10603                 case $1 in
10604                         cpu)
10605                                 app_cpu=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
10606                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10607                                         extra_data=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
10608                                 fi
10609                                 ;;
10610                         mem)
10611                                 app_mem=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
10612                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10613                                         extra_data=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
10614                                 fi
10615                                 ;;
10616                 esac
10617                 (( line_counter++ ))
10618                 count_nu="${C1}$line_counter:${C2}"
10619                 full_line="$count_nu$app_cpu$app_mem$app_name$app_pid$extra_data"
10620                 ps_data=$( create_print_line " " "$full_line" )
10621                 print_screen_output "$ps_data"
10622         done
10623         
10624         eval $LOGFE
10625 }
10626
10627 print_raid_data()
10628 {
10629         eval $LOGFS
10630         local device='' device_string='' device_state='' raid_level='' device_components=''
10631         local device_report='' u_data='' blocks='' super_blocks='' algorithm='' chunk_size=''
10632         local bitmap_values='' recovery_progress_bar='' recovery_percent='' recovered_sectors=''
10633         local finish_time='' recovery_speed='' raid_counter=0 device_counter=1 basic_counter=1
10634         local a_raid_working='' raid_data='' kernel_support='' read_ahead='' unused_devices=''
10635         local basic_raid='' basic_raid_separator='' basic_raid_plural='' inactive=''
10636         local component_separator='' device_id='' print_string='' loop_limit=0 array_count_unused=''
10637         local array_count='' raid_event='' b_print_lines='true'
10638         local no_raid_detected='' dev_string='/dev/'
10639         local empty_raid_data='' report_size='report' blocks_avail='blocks' chunk_raid_usage='chunk size'
10640         
10641         if [[ -n $BSD_TYPE ]];then
10642                 no_raid_detected='No zfs software RAID detected - other types not yet supported.'
10643                 empty_raid_data='No zfs RAID data available - other types not yet supported.'
10644                 report_size='full size'
10645                 blocks_avail='available size'
10646                 chunk_raid_usage='raid allocated'
10647         else
10648                 no_raid_detected="No RAID data available - $FILE_MDSTAT is missing - is md_mod kernel module loaded?"
10649                 empty_raid_data="No RAID devices detected - $FILE_MDSTAT and md_mod kernel raid module present"
10650         fi
10651         
10652         if [[ $BSD_TYPE == 'bsd' ]];then
10653                 dev_string=''
10654         fi
10655         if [[ $B_RAID_SET != 'true' ]];then
10656                 get_raid_data
10657         fi
10658
10659         for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
10660         do
10661                 IFS=","
10662                 a_raid_working=(${A_RAID_DATA[i]})
10663                 IFS="$ORIGINAL_IFS"
10664                 
10665                 # reset on each iteration
10666                 algorithm=''
10667                 bitmap_values=''
10668                 blocks=''
10669                 component_separator=''
10670                 device=''
10671                 device_components=''
10672                 device_id=''
10673                 device_report=''
10674                 device_state=''
10675                 failed=''
10676                 finish_time=''
10677                 inactive=''
10678                 raid_event=''
10679                 raid_level=''
10680                 recovery_percent=''
10681                 recovery_progress_bar=''
10682                 recovered_sectors=''
10683                 recovery_speed=''
10684                 spare=''
10685                 super_blocks=''
10686                 u_data=''
10687                 
10688                 if [[ -n $( grep '^md' <<< ${a_raid_working[0]} ) && -z $BSD_TYPE ]] || \
10689                 [[ -n $BSD_TYPE && ${a_raid_working[0]} != '' ]];then
10690                         if [[ $B_SHOW_BASIC_RAID == 'true' ]];then
10691                                 if [[ $basic_raid != '' ]];then
10692                                         basic_raid_plural='s'
10693                                 fi
10694                                 if [[ ${a_raid_working[1]} == 'inactive' ]];then
10695                                         inactive=" - ${a_raid_working[1]}"
10696                                 fi
10697                                 basic_raid="$basic_raid$basic_raid_separator${C1}$basic_counter${SEP3}${C2} $dev_string${a_raid_working[0]}$inactive"
10698                                 basic_raid_separator=' '
10699                                 (( basic_counter++ ))
10700                         else
10701                                 device_id="-$device_counter"
10702                                 device="$dev_string${a_raid_working[0]}"
10703                                 
10704                                 (( device_counter++ ))
10705                                 if [[ ${a_raid_working[1]} != '' ]];then
10706                                         device_state=" - ${a_raid_working[1]}"
10707                                 fi
10708                                 
10709                                 if [[ ${a_raid_working[2]} == '' ]];then
10710                                         raid_level='N/A'
10711                                 else
10712                                         raid_level=${a_raid_working[2]}
10713                                 fi
10714                                 # there's one case: md0 : inactive  that has to be protected against
10715                                 if [[ ${a_raid_working[2]} == '' && ${a_raid_working[1]} == 'inactive' ]];then
10716                                         raid_level=''
10717                                 else
10718                                         raid_level=" ${C1}raid${SEP3}${C2} $raid_level"
10719                                 fi
10720                                 if [[ ${a_raid_working[4]} != '' ]];then
10721                                         device_report="${a_raid_working[4]}"
10722                                 else
10723                                         device_report="N/A"
10724                                 fi
10725                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10726                                         if [[ ${a_raid_working[6]} != '' ]];then
10727                                                 blocks=${a_raid_working[6]}
10728                                         else
10729                                                 blocks='N/A'
10730                                         fi
10731                                         blocks=" ${C1}$blocks_avail${SEP3}${C2} $blocks"
10732                                         
10733                                         if [[ ${a_raid_working[9]} != '' ]];then
10734                                                 chunk_size=${a_raid_working[9]}
10735                                         else
10736                                                 chunk_size='N/A'
10737                                         fi
10738                                         chunk_size=" ${C1}$chunk_raid_usage${SEP3}${C2} $chunk_size"
10739                                         if [[ ${a_raid_working[10]} != '' ]];then
10740                                                 bitmap_value='true'
10741                                                 bitmap_value=" ${C1}bitmap${SEP3}${C2} $bitmap_value"
10742                                         fi
10743                                 fi
10744                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10745                                         if [[ ${a_raid_working[5]} != '' ]];then
10746                                                 u_data=" ${a_raid_working[5]}"
10747                                         fi
10748                                         if [[ ${a_raid_working[7]} != '' ]];then
10749                                                 super_blocks=" ${C1}super blocks${SEP3}${C2} ${a_raid_working[7]}"
10750                                         fi
10751                                         if [[ ${a_raid_working[8]} != '' ]];then
10752                                                 algorithm=" ${C1}algorithm${SEP3}${C2} ${a_raid_working[8]}"
10753                                         fi
10754                                 fi
10755                                 if [[ ${a_raid_working[3]} == '' ]];then
10756                                         if [[ ${a_raid_working[1]} != 'inactive' ]];then
10757                                                 device_components='N/A'
10758                                         fi
10759                                 else
10760                                         for component in ${a_raid_working[3]}
10761                                         do
10762                                                 if [[ $B_EXTRA_DATA != 'true' ]];then
10763                                                         component=$( sed 's/\[[0-9]\+\]//' <<< $component )
10764                                                 fi
10765                                                 # NOTE: for bsd zfs, states are: ONLINE,DEGRADED,OFFLINE (at least)
10766                                                 if [[ -n $( grep -E '(F|DEGRADED)' <<< $component ) ]];then
10767                                                         component=$( sed -e 's/(F)//' -e 's/F//' -e 's/DEGRADED//' <<<  $component )
10768                                                         failed="$failed $component"
10769                                                         component=''
10770                                                 elif [[ -n $( grep -E '(S|OFFLINE)' <<< $component ) ]];then
10771                                                         component=$( sed -e 's/(S)//' -e 's/S//' -e 's/OFFLINE//' <<<  $component )
10772                                                         spare="$spare $component"
10773                                                         component=''
10774                                                 else
10775                                                         device_components="$device_components$component_separator$component"
10776                                                         component_separator=' '
10777                                                 fi
10778                                         done
10779
10780                                         if [[ $failed != '' ]];then
10781                                                 failed=" ${C1}FAILED${SEP3}${C2}$failed${C2}"
10782                                         fi
10783                                         if [[ $spare != '' ]];then
10784                                                 spare=" ${C1}spare${SEP3}${C2}$spare${C2}"
10785                                         fi
10786                                         
10787                                         if [[ -n $device_components || -n $spare || -n $failed ]];then
10788                                                 if [[ $B_EXTRA_DATA != 'true' && -z $BSD_TYPE ]];then
10789                                                         if [[ $device_report != 'N/A' && -n $device_components ]];then
10790                                                                 device_components="$device_report - $device_components"
10791                                                         fi
10792                                                 fi
10793                                                 if [[ $device_components == '' ]];then
10794                                                         device_components='none'
10795                                                 fi
10796                                                 device_components="${C1}online${SEP3}${C2} $device_components"
10797                                                 device_components=" ${C1}components${SEP3}${C2} $device_components$failed$spare"
10798                                         fi
10799                                 fi
10800                                 a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$raid_level$device_components"
10801                                 
10802                                 if [[ $B_EXTRA_DATA == 'true' && ${a_raid_working[1]} != 'inactive' ]];then
10803                                         a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$device_components"
10804                                         (( raid_counter++ ))
10805                                         print_string="${C1}Info${SEP3}${C2}$raid_level ${C1}$report_size${SEP3}${C2} $device_report$u_data"
10806                                         print_string="$print_string$blocks$chunk_size$bitmap_value$super_blocks$algorithm"
10807                                         a_raid_data[$raid_counter]="$print_string"
10808                                 else
10809                                         a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$raid_level$device_components"
10810                                 fi
10811                                 (( raid_counter++ ))
10812                                 
10813                                 # now let's do the recover line if required
10814                                 if [[ ${a_raid_working[12]} != '' ]];then
10815                                         recovery_percent=$( cut -d '~' -f 2 <<< ${a_raid_working[12]} )
10816                                         if [[ ${a_raid_working[14]} != '' ]];then
10817                                                 finish_time=${a_raid_working[14]}
10818                                         else
10819                                                 finish_time='N/A'
10820                                         fi
10821                                         finish_time=" ${C1}time remaining${SEP3}${C2} $finish_time"
10822                                         if [[ $B_EXTRA_DATA == 'true' ]];then
10823                                                 if [[ ${a_raid_working[13]} != '' ]];then
10824                                                         recovered_sectors=" ${C1}sectors${SEP3}${C2} ${a_raid_working[13]}"
10825                                                 fi
10826                                         fi
10827                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10828                                                 if [[ ${a_raid_working[11]} != '' ]];then
10829                                                         recovery_progress_bar=" ${a_raid_working[11]}"
10830                                                 fi
10831                                                 if [[ ${a_raid_working[15]} != '' ]];then
10832                                                         recovery_speed=" ${C1}speed${SEP3}${C2} ${a_raid_working[15]}"
10833                                                 fi
10834                                         fi
10835                                         
10836                                         a_raid_data[$raid_counter]="${C1}Recovering${SEP3}${C2} $recovery_percent$recovery_progress_bar$recovered_sectors$finish_time$recovery_speed"
10837                                         (( raid_counter++ ))
10838                                 fi
10839                         fi
10840                 elif [[ ${a_raid_working[0]} == 'KernelRaidSupport' ]];then
10841                         if [[ ${a_raid_working[1]} == '' ]];then
10842                                 kernel_support='N/A'
10843                         else
10844                                 kernel_support=${a_raid_working[1]}
10845                         fi
10846                         kernel_support=" ${C1}supported${SEP3}${C2} $kernel_support"
10847                 elif [[ ${a_raid_working[0]} == 'ReadAhead' ]];then
10848                         if [[ ${a_raid_working[1]} != '' ]];then
10849                                 read_ahead=${a_raid_working[1]}
10850                                 read_ahead=" ${C1}read ahead${SEP3}${C2} $read_ahead"
10851                         fi
10852                 elif [[ ${a_raid_working[0]} == 'UnusedDevices' ]];then
10853                         if [[ ${a_raid_working[1]} == '' ]];then
10854                                 unused_devices='N/A'
10855                         else
10856                                 unused_devices=${a_raid_working[1]}
10857                         fi
10858                         unused_devices="${C1}Unused Devices${SEP3}${C2} $unused_devices"
10859                 elif [[ ${a_raid_working[0]} == 'raidEvent' ]];then
10860                         if [[ ${a_raid_working[1]} != '' ]];then
10861                                 raid_event=${a_raid_working[1]}
10862                                 raid_event=" ${C1}Raid Event${SEP3}${C2} ${a_raid_working[1]}"
10863                         fi
10864                 fi
10865         done
10866         
10867         if [[ $B_SHOW_BASIC_RAID == 'true' && $basic_raid != '' ]];then
10868                 a_raid_data[0]="${C1}Device$basic_raid_plural${SEP3}${C2} $basic_raid"
10869         fi
10870         # note bsd temp test hack to make it run
10871         if [[ $B_MDSTAT_FILE != 'true' && -z $BSD_TYPE ]] || \
10872         [[ -n $BSD_TYPE && $B_BSD_RAID == 'false' ]];then
10873                 if [[ $B_SHOW_RAID_R == 'true' ]];then
10874                         a_raid_data[0]="$no_raid_detected"
10875                 else
10876                         b_print_lines='false'
10877                 fi
10878         else
10879                 if [[ ${a_raid_data[0]} == '' ]];then
10880                         if [[ $B_SHOW_BASIC_RAID != 'true' ]];then
10881                                 a_raid_data[0]="$empty_raid_data"
10882                         else
10883                                 b_print_lines='false'
10884                         fi
10885                 fi
10886                 # now let's add on the system line and the unused device line. Only print on -xx
10887                 if [[ $kernel_support$read_ahead$raid_event != '' ]];then
10888                         array_count=${#a_raid_data[@]}
10889                         a_raid_data[array_count]="${C1}System${SEP3}${C2}$kernel_support$read_ahead$raid_event"
10890                         loop_limit=1
10891                 fi
10892                 if [[ $unused_devices != '' ]];then
10893                         array_count_unused=${#a_raid_data[@]}
10894                         a_raid_data[array_count_unused]="$unused_devices"
10895                         loop_limit=2
10896                 fi
10897         fi
10898
10899         # we don't want to print anything if it's -b and no data is present, just a waste of a line
10900         if [[ $b_print_lines == 'true' ]];then
10901                 # print out all lines, line starter on first line
10902                 for (( i=0; i < ${#a_raid_data[@]} - $loop_limit;i++ ))
10903                 do
10904                         if [[ $i -eq 0 ]];then
10905                                 line_starter='RAID:'
10906                         else
10907                                 line_starter=' '
10908                         fi
10909                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count != '' ]];then
10910                                 if [[ $i == 0 ]];then
10911                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count]}" )
10912                                         print_screen_output "$raid_data"
10913                                         line_starter=' '
10914                                 fi
10915                         fi
10916                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[i]}" )
10917                         print_screen_output "$raid_data"
10918                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count_unused != '' ]];then
10919                                 if [[ $i == $(( array_count_unused - 2 )) ]];then
10920                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count_unused]}" )
10921                                         print_screen_output "$raid_data"
10922                                 fi
10923                         fi
10924                 done
10925         fi
10926         
10927         eval $LOGFE
10928 }
10929
10930 # currently only apt using distros support this feature, but over time we can add others
10931 print_repo_data()
10932 {
10933         eval $LOGFS
10934         local repo_count=0 repo_line='' file_name='' file_content='' file_name_holder=''
10935         local repo_full='' b_print_next_line='false' repo_type=''
10936         
10937         get_repo_data
10938         
10939         if [[ -n $REPO_DATA ]];then
10940                 # loop through the variable's lines one by one, update counter each iteration
10941                 while read repo_line
10942                 do
10943                         (( repo_count++ ))
10944                         repo_type=$( cut -d ':' -f 1 <<< $repo_line )
10945                         file_name=$( cut -d ':' -f 2 <<< $repo_line )
10946                         file_content=$( cut -d ':' -f 3-7 <<< $repo_line )
10947                         # this will dump unwanted white space line starters. Some irc channels
10948                         # use bots that show page title for urls, so need to break the url by adding 
10949                         # a white space.
10950                         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
10951                                 file_content=$( echo $file_content | sed 's|://|: //|' )
10952                         else
10953                                 file_content=$( echo $file_content )
10954                         fi
10955                         # echo $file_name : $file_name_holder : $repo_type : $file_content
10956                         # check file name, if different, update the holder for print out
10957                         if [[ $file_name != $file_name_holder ]];then
10958                                 if [[ $repo_type == 'pisi repo' || $repo_type == 'urpmq repo' ]];then
10959                                         repo_full="${C1}$repo_type:${C2} $file_name"
10960                                 else
10961                                         repo_full="${C1}Active $repo_type in file:${C2} $file_name"
10962                                 fi
10963                                 file_name_holder=$file_name
10964                                 b_print_next_line='true'
10965                         else
10966                                 repo_full=$file_content
10967                         fi
10968                         # first line print Repos: 
10969                         if [[ $repo_count -eq 1 ]];then
10970                                 repo_full=$( create_print_line "Repos:" "$repo_full" )
10971                         else
10972                                 repo_full=$( create_print_line " " "$repo_full" )
10973                         fi
10974                         print_screen_output "$repo_full"
10975                         # this prints the content of the file as well as the file name
10976                         if [[ $b_print_next_line == 'true' ]];then
10977                                 repo_full=$( create_print_line " " "$file_content" )
10978                                 print_screen_output "$repo_full"
10979                                 b_print_next_line='false'
10980                         fi
10981                 done <<< "$REPO_DATA"
10982         else
10983                 repo_full=$( create_print_line "Repos:" "${C1}Error:${C2} $SCRIPT_NAME does not support this feature for your distro yet." )
10984                 print_screen_output "$repo_full"
10985         fi
10986         eval $LOGFE
10987 }
10988
10989 print_sensors_data()
10990 {
10991         eval $LOGFS
10992         local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' 
10993         local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp=''
10994         local a_sensors_working=''
10995         local no_sensors_message='None detected - is lm-sensors installed and configured?'
10996         local Sensors_Data="$( get_sensors_output )"
10997         get_sensors_data
10998         
10999         if [[ $BSD_TYPE == 'bsd' ]];then
11000                 no_sensors_message='This feature is not yet supported for BSD systems.'
11001         fi
11002         
11003         IFS=","
11004         a_sensors_working=( ${A_SENSORS_DATA[0]} )
11005         IFS="$ORIGINAL_IFS"
11006         # initial error cases, for missing app or unconfigured sensors. Note that array 0
11007         # always has at least 3 items, cpu/mobo/psu temp in it. If the count is 0, then
11008         # no sensors are installed/configured
11009         if [[ ${#a_sensors_working[@]} -eq 0 ]];then
11010                 cpu_temp=$no_sensors_message
11011                 b_is_error='true'
11012         else
11013                 for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ ))
11014                 do
11015                         IFS=","
11016                         a_sensors_working=( ${A_SENSORS_DATA[i]} )
11017                         IFS="$ORIGINAL_IFS"
11018                         case $i in
11019                                 # first the temp data
11020                                 0)
11021                                         if [[ -n ${a_sensors_working[0]} ]];then
11022                                                 cpu_temp=${a_sensors_working[0]}
11023                                         else
11024                                                 cpu_temp='N/A'
11025                                         fi
11026                                         cpu_temp="${C1}System Temperatures: cpu$SEP3${C2} $cpu_temp "
11027
11028                                         if [[ -n ${a_sensors_working[1]} ]];then
11029                                                 mobo_temp=${a_sensors_working[1]}
11030                                         else
11031                                                 mobo_temp='N/A'
11032                                         fi
11033                                         mobo_temp="${C1}mobo$SEP3${C2} $mobo_temp "
11034
11035                                         if [[ -n ${a_sensors_working[2]} ]];then
11036                                                 psu_temp="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
11037                                         fi
11038                                         gpu_temp=$( get_gpu_temp_data )
11039                                         # dump the unneeded screen data for single gpu systems 
11040                                         if [[ $( wc -w <<< $gpu_temp ) -eq 1 && $B_EXTRA_DATA != 'true' ]];then
11041                                                 gpu_temp=${gpu_temp#*:}
11042                                         fi
11043                                         if [[ -n $gpu_temp ]];then
11044                                                 gpu_temp="${C1}gpu$SEP3${C2} ${gpu_temp} "
11045                                         fi
11046                                         ;;
11047                                 # then the fan data from main fan array
11048                                 1)
11049                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
11050                                         do
11051                                                 case $j in
11052                                                         0)
11053                                                                 # we need to make sure it's either cpu fan OR cpu fan and sys fan 1
11054                                                                 if [[ -n ${a_sensors_working[0]} ]];then
11055                                                                         cpu_fan="${a_sensors_working[0]}"
11056                                                                 elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then
11057                                                                         cpu_fan="${a_sensors_working[1]}"
11058                                                                 else
11059                                                                         cpu_fan='N/A'
11060                                                                 fi
11061                                                                 cpu_fan="${C1}Fan Speeds (in rpm): cpu$SEP3${C2} $cpu_fan "
11062                                                                 (( fan_count++ ))
11063                                                                 ;;
11064                                                         1)
11065                                                                 if [[ -n ${a_sensors_working[1]} ]];then
11066                                                                         mobo_fan="${C1}mobo$SEP3${C2} ${a_sensors_working[1]} "
11067                                                                         (( fan_count++ ))
11068                                                                 fi
11069                                                                 ;;
11070                                                         2)
11071                                                                 if [[ -n ${a_sensors_working[2]} ]];then
11072                                                                         ps_fan="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
11073                                                                         (( fan_count++ ))
11074                                                                 fi
11075                                                                 ;;
11076                                                         [3-9]|[1-9][0-9])
11077                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
11078                                                                         fan_number=$(( $j - 2 )) # sys fans start on array key 5
11079                                                                         # wrap after fan 6 total
11080                                                                         if [[ $fan_count -lt 7 ]];then
11081                                                                                 sys_fans="$sys_fans${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11082                                                                         else
11083                                                                                 sys_fans2="$sys_fans2${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11084                                                                         fi
11085                                                                         (( fan_count++ ))
11086                                                                 fi
11087                                                                 ;;
11088                                                 esac
11089                                         done
11090                                         ;;
11091                                 2)
11092                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
11093                                         do
11094                                                 case $j in
11095                                                         [0-9]|[1-9][0-9])
11096                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
11097                                                                         fan_number=$(( $j + 1 )) # sys fans start on array key 5
11098                                                                         # wrap after fan 6 total
11099                                                                         if [[ $fan_count -lt 7 ]];then
11100                                                                                 sys_fans="$sys_fans${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11101                                                                         else
11102                                                                                 sys_fans2="$sys_fans2${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11103                                                                         fi
11104                                                                         (( fan_count++ ))
11105                                                                 fi
11106                                                                 ;;
11107                                                 esac
11108                                         done
11109                                         ;;
11110                         esac
11111                 done
11112         fi
11113         # turning off all output for case where no sensors detected or no sensors output 
11114         # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used
11115         if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then
11116                 temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp"
11117                 temp_data=$( create_print_line "Sensors:" "$temp_data" )
11118                 print_screen_output "$temp_data"
11119                 # don't print second or subsequent lines if error data
11120                 fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans"
11121                 if [[ $b_is_error != 'true' && -n $fan_data ]];then
11122                         fan_data=$( create_print_line " " "$fan_data" )
11123                         print_screen_output "$fan_data"
11124                         # and then second wrapped fan line if needed
11125                         if [[ -n $sys_fans2 ]];then
11126                                 fan_data2=$( create_print_line " " "$sys_fans2" )
11127                                 print_screen_output "$fan_data2"
11128                         fi
11129                 fi
11130         fi
11131         eval $LOGFE
11132 }
11133
11134 print_system_data()
11135 {
11136         eval $LOGFS
11137         local system_data='' bits='' desktop_environment='' dm_data='' de_extra_data=''
11138         local host_kernel_string='' de_distro_string='' host_string='' desktop_type='Desktop'
11139         local host_name=$HOSTNAME
11140         local current_kernel=$( get_kernel_version ) 
11141         local distro="$( get_distro_data )"
11142         local tty_session=''
11143         
11144         # I think these will work, maybe, if logged in as root and in X
11145         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
11146                 desktop_environment=$( get_desktop_environment )
11147                 if [[ -z $desktop_environment ]];then
11148                         desktop_environment='N/A'
11149                 fi
11150                 
11151                 if [[  $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
11152                         de_extra_data=$( get_desktop_extra_data )
11153                         if [[ -n $de_extra_data ]];then
11154                                 de_extra_data=" ${C1}info$SEP3${C2} $de_extra_data"
11155                         fi
11156                 fi
11157         else
11158                 tty_session=$( get_tty_number )
11159                 if [[ -z $tty_session && $B_CONSOLE_IRC == 'true' ]];then
11160                         tty_session=$( get_tty_console_irc )
11161                 fi
11162                 if [[ -n $tty_session ]];then
11163                         tty_session=" $tty_session"
11164                 fi
11165                 desktop_environment="tty$tty_session"
11166                 desktop_type='Console'
11167         fi
11168         # having dm type can be useful if you are accessing remote system
11169         # or are out of X and don't remember which dm is running the system
11170         if [[  $B_EXTRA_EXTRA_DATA == 'true' ]];then
11171                 dm_data=$( get_display_manager )
11172                 # here we only want the dm info to show N/A if in X
11173                 if [[ -z $dm_data && $B_RUNNING_IN_DISPLAY == 'true' ]];then
11174                         dm_data='N/A'
11175                 fi
11176                 # only print out of X if dm_data has info, then it's actually useful, but
11177                 # for headless servers, no need to print dm stuff.
11178                 if [[ -n $dm_data ]];then
11179                         dm_data=" ${C1}dm$SEP3${C2} $dm_data"
11180                 fi
11181         fi
11182         
11183         de_distro_string="${C1}$desktop_type$SEP3${C2} $desktop_environment$de_extra_data$dm_data ${C1}Distro$SEP3${C2} $distro"
11184         if [[ $B_EXTRA_DATA == 'true' ]];then
11185                 gcc_string=$( get_gcc_kernel_version )
11186                 if [[ -n $gcc_string ]];then
11187                         gcc_string=", ${C1}gcc$SEP3${C2} $gcc_string"
11188                 fi
11189         fi
11190         # check for 64 bit first
11191         if [[ -n $( uname -m | grep -E '(x86_64|amd64)' ) ]];then
11192                 bits="64"
11193         else
11194                 bits="32"
11195         fi
11196         bits=" (${bits} bit${gcc_string})"
11197         if [[ $B_SHOW_HOST == 'true' ]];then
11198                 if [[ -z $HOSTNAME ]];then
11199                         if [[ -n $( type p hostname ) ]];then
11200                                 host_name=$( hostname )
11201                         fi
11202                         if [[ -z $host_name ]];then
11203                                 host_name='N/A'
11204                         fi
11205                 fi
11206                 host_string="${C1}Host$SEP3${C2} $host_name "
11207                 system_data=$( create_print_line "System:" "$host_string$host_name ${C1}Kernel$SEP3${C2}" )
11208         fi
11209         host_kernel_string="$host_string${C1}Kernel$SEP3${C2} $current_kernel$bits "
11210         if [[ $( calculate_line_length "$host_kernel_string$de_distro_string" ) -lt $COLS_INNER ]];then
11211                 system_data="$host_kernel_string$de_distro_string"
11212                 system_data=$( create_print_line "System:" "$system_data" )
11213         else
11214                 system_data=$( create_print_line "System:" "$host_kernel_string" )
11215                 print_screen_output "$system_data"
11216                 system_data=$( create_print_line " " "$de_distro_string" )
11217         fi
11218         print_screen_output "$system_data"
11219         eval $LOGFE
11220 }
11221
11222 print_unmounted_partition_data()
11223 {
11224         eval $LOGFS
11225         local a_unmounted_data='' line_starter='' unmounted_data='' full_fs=''
11226         local full_dev='' full_size='' full_label='' full_uuid='' full_string=''
11227         local bsd_unsupported='This feature is not yet supported for BSD systems.'
11228         
11229         if [[ -z ${A_PARTITION_DATA} ]];then
11230                 get_partition_data
11231         fi
11232         get_unmounted_partition_data
11233         
11234         if [[ ${#A_UNMOUNTED_PARTITION_DATA[@]} -ge 1 ]];then
11235                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
11236                 do
11237                         IFS=","
11238                         a_unmounted_data=(${A_UNMOUNTED_PARTITION_DATA[i]})
11239                         IFS="$ORIGINAL_IFS"
11240                         if [[ -z ${a_unmounted_data[0]} ]];then
11241                                 full_dev='N/A'
11242                         else
11243                                 full_dev="/dev/${a_unmounted_data[0]}"
11244                         fi
11245                         full_dev="${C1}ID:${C2} $full_dev"
11246                         if [[ -z ${a_unmounted_data[1]} ]];then
11247                                 full_size='N/A'
11248                         else
11249                                 full_size=${a_unmounted_data[1]}
11250                         fi
11251                         full_size="${C1}size$SEP3${C2} $full_size"
11252                         if [[ -z ${a_unmounted_data[2]} ]];then
11253                                 full_label='N/A'
11254                         else
11255                                 full_label=${a_unmounted_data[2]}
11256                         fi
11257                         full_label="${C1}label$SEP3${C2} $full_label"
11258                         if [[ -z ${a_unmounted_data[3]} ]];then
11259                                 full_uuid='N/A'
11260                         else
11261                                 full_uuid=${a_unmounted_data[3]}
11262                         fi
11263                         full_uuid="${C1}uuid$SEP3${C2} $full_uuid"
11264                         if [[ -z ${a_unmounted_data[4]} ]];then
11265                                 full_fs=''
11266                         else
11267                                 full_fs="${C1}fs$SEP3${C2} ${a_unmounted_data[4]}"
11268                         fi
11269                         full_string="$full_dev $full_size $full_label $full_uuid $full_fs"
11270                         if [[ $i -eq 0 ]];then
11271                                 line_starter='Unmounted:'
11272                         else
11273                                 line_starter=' '
11274                         fi
11275                         # temporary message to indicate not yet supported
11276                         if [[ $BSD_TYPE == 'bsd' ]];then
11277                                 full_string=$bsd_unsupported
11278                         fi
11279                         unmounted_data=$( create_print_line "$line_starter" "$full_string" )
11280                         print_screen_output "$unmounted_data"
11281                 done
11282         else
11283                 unmounted_data=$( create_print_line "Unmounted:" "No unmounted partitions detected" )
11284                 print_screen_output "$unmounted_data"
11285         fi
11286         
11287         eval $LOGFE
11288 }
11289
11290 print_weather_data()
11291 {
11292         eval $LOGFS
11293         
11294         local weather_data='' location_string='' local_time='' time_string='' pressure=''
11295         local a_location='' a_weather='' weather_string='' weather='' temp='' winds='' humidity=''
11296         local time_zone='' observation_time='' city='' state='' country='' altitude=''
11297         local heat_index="" wind_chill='' dewpoint='' xxx_humidity=''
11298         local openP='(' closeP=')'
11299         
11300         if [[ $B_RUNNING_IN_SHELL == 'false' ]];then
11301                 openP=''
11302                 closeP=''
11303         fi
11304         
11305         get_weather_data
11306         
11307         # city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
11308         #  ";" latitude "," longitude ";" postalCode ";" timeZone
11309         
11310         # observationTime ";" localTime ";" weather ";" tempString ";" humidity 
11311         # ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
11312         # ";" windChillString ";" siteElevation
11313
11314         if [[ ${#A_WEATHER_DATA[@]} -eq 2 ]];then
11315                 IFS=";"
11316                 a_location=(${A_WEATHER_DATA[0]})
11317                 a_weather=(${A_WEATHER_DATA[1]})
11318                 IFS="$ORIGINAL_IFS"
11319                 
11320                 if [[ -n ${a_weather[3]} ]];then
11321                         temp=${a_weather[3]}
11322                 else
11323                         temp='N/A'
11324                 fi
11325                 if [[ -n ${a_weather[2]} ]];then
11326                         weather=" - ${a_weather[2]}"
11327                 else
11328                         weather=''
11329                 fi
11330                 if [[ $B_EXTRA_DATA == 'true' ]];then
11331                         if [[ -n ${a_weather[5]} ]];then
11332                                 winds=" ${C1}Wind$SEP3${C2} ${a_weather[5]}"
11333                         fi
11334                 fi
11335                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11336                         if [[ -n ${a_weather[4]} ]];then
11337                                 humidity=" ${C1}Humidity$SEP3${C2} ${a_weather[4]}"
11338                         fi
11339                         if [[ -n ${a_weather[6]} ]];then
11340                                 pressure="${C1}Pressure$SEP3${C2} ${a_weather[6]} "
11341                         fi
11342                 fi
11343                 weather_string="${C1}Conditions$SEP3${C2} $temp$weather$winds$humidity"
11344                 
11345                 if [[ -n ${a_weather[1]} ]];then
11346                         local_time=" ${a_weather[1]}"
11347                 else
11348                         local_time=" $(date)"
11349                 fi
11350                 if [[ $B_EXTRA_DATA == 'true' && -n ${a_location[8]} ]];then
11351                         time_zone=" (${a_location[8]})"
11352                 fi
11353                 time_string="${C1}Time$SEP3${C2}$local_time$time_zone"
11354
11355                 if [[ $B_EXTRA_DATA != 'true' ]];then
11356                         weather_data="$weather_string $time_string"
11357                         weather_data=$( create_print_line "Weather:" "$weather_data" )
11358                         print_screen_output "$weather_data"
11359                 else
11360                         weather_data="$weather_string"
11361                         weather_data=$( create_print_line "Weather:" "$weather_data" )
11362                         print_screen_output "$weather_data"
11363                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
11364                                 if [[ -n ${a_weather[8]} ]];then
11365                                         heat_index="${C1}Heat Index$SEP3${C2} ${a_weather[8]} "
11366                                 fi
11367                                 if [[ -n ${a_weather[9]} ]];then
11368                                         wind_chill="${C1}Wind Chill$SEP3${C2} ${a_weather[9]} "
11369                                 fi
11370                                 if [[ -n ${a_weather[7]} ]];then
11371                                         dew_point="${C1}Dew Point$SEP3${C2} ${a_weather[7]} "
11372                                 fi
11373                                 if [[ -n ${a_weather[0]} ]];then
11374                                         observation_time=" ${C1}Observation Time$SEP3${C2} ${a_weather[0]} "
11375                                 fi
11376                                 if [[ $B_OUTPUT_FILTER != 'true' ]];then
11377                                         if [[ -n ${a_location[0]} ]];then
11378                                                 city=" ${a_location[0]}"
11379                                         fi
11380                                         if [[ -n ${a_location[1]} ]];then
11381                                                 state=" ${a_location[1]}"
11382                                         fi
11383                                         if [[ -n ${a_location[5]} ]];then
11384                                                 country=" $openP${a_location[5]}$closeP"
11385                                         fi
11386                                         if [[ -n ${a_weather[10]} ]];then
11387                                                 altitude=" ${C1}Altitude$SEP3${C2} ${a_weather[10]}"
11388                                         fi
11389                                         location_string="${C1}Location$SEP3${C2}$city$state$country$altitude "
11390                                 else
11391                                         location_string=$time_string$observation_time
11392                                         time_string=''
11393                                         observation_time=''
11394                                 fi
11395                                 # the last three are oftenblank
11396                                 if [[ -z "$heat_index$wind_chill$dew_point" ]];then
11397                                         weather_data=$( create_print_line " " "$pressure$location_string" )
11398                                         print_screen_output "$weather_data"
11399                                 else
11400                                         weather_data=$( create_print_line " " "$pressure$heat_index$wind_chill$dew_point" )
11401                                         print_screen_output "$weather_data"
11402                                         if [[ $B_OUTPUT_FILTER != 'true' ]];then
11403                                                 weather_data=$( create_print_line " " "$location_string" )
11404                                                 print_screen_output "$weather_data"
11405                                         fi
11406                                 fi
11407                                 if [[ -n $time_string$observation_time ]];then
11408                                         weather_data=$( create_print_line " " "$time_string$observation_time" )
11409                                         print_screen_output "$weather_data"
11410                                 fi
11411                         else
11412                                 if [[ -n $pressure$time_string ]];then
11413                                         weather_data="$pressure$time_string"
11414                                         weather_data=$( create_print_line " " "$weather_data" )
11415                                         print_screen_output "$weather_data"
11416                                 fi
11417                         fi
11418                 fi
11419         else
11420                 weather_data=$( create_print_line "Weather:" "Weather data failure: $(date)" )
11421                 print_screen_output "$weather_data"
11422                 weather_data=$( create_print_line " " "${A_WEATHER_DATA}" )
11423                 print_screen_output "$weather_data"
11424         fi
11425         eval $LOGFE
11426 }
11427
11428 ########################################################################
11429 #### SCRIPT EXECUTION
11430 ########################################################################
11431
11432 main $@ ## From the End comes the Beginning
11433
11434 ## note: this EOF is needed for smxi handling, this is what triggers the full download ok
11435 ###**EOF**###