a7c2528d3cc181eeb59d5015a4b6102b8837a02b
[quassel.git] / data / scripts / inxi
1 #!/usr/bin/env bash
2 ########################################################################
3 ####  Script Name: inxi
4 ####  Version: 2.1.1
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 # http://stackoverflow.com/questions/1780483/lines-and-columns-environmental-variables-lost-in-a-script
498 if [[ -n $( type -p tput ) ]];then
499         TERM_COLUMNS=$(tput cols)
500         TERM_LINES=$(tput lines)
501 fi
502 # double check, just in case it's missing functionality or whatever
503 if [[ -n ${TERM_COLUMNS##[0-9]*} ]];then
504         TERM_COLUMNS=80
505         TERM_LINES=100
506 fi
507
508 # Only for legacy user config files se we can test and convert the var name
509 LINE_MAX_CONSOLE=''
510 LINE_MAX_IRC=''
511
512 ### COLORS ###
513 # Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Use following variables in config 
514 # files to change defaults for each type, or global
515 # Same as runtime parameter.
516 DEFAULT_COLOR_SCHEME=2
517 ## color variables - set dynamically
518 COLOR_SCHEME=''
519 C1=''
520 C2=''
521 CN=''
522 ## Always leave these blank, these are only going to be set in inxi.conf files, that makes testing
523 ## for user changes easier after sourcing the files
524 GLOBAL_COLOR_SCHEME=''
525 IRC_COLOR_SCHEME=''
526 IRC_CONS_COLOR_SCHEME=''
527 IRC_X_TERM_COLOR_SCHEME=''
528 CONSOLE_COLOR_SCHEME=''
529 VIRT_TERM_COLOR_SCHEME=''
530
531 ## Output colors
532 # A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below.
533 unset EMPTY
534 #             DGREY   BLACK   RED     DRED    GREEN   DGREEN  YELLOW  DYELLOW
535 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"
536 IRC_COLORS="  \x0314  \x0301  \x0304  \x0305  \x0309  \x0303  \x0308  \x0307"
537 #                          BLUE    DBLUE   MAGENTA DMAGENTA CYAN   DCYAN   WHITE   GREY    NORMAL
538 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"
539 IRC_COLORS=" $IRC_COLORS    \x0312 \x0302  \x0313  \x0306  \x0311  \x0310  \x0300  \x0315  \x03"
540
541 #ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS)
542 A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL )
543
544 # See above for notes on EMPTY
545 ## note: group 1: 0, 1 are null/normal
546 ## Following: group 2: generic, light/dark or dark/light; group 3: dark on light; group 4 light on dark; 
547 # this is the count of the first two groups, starting at zero
548 SAFE_COLOR_COUNT=12
549 A_COLOR_SCHEMES=( 
550 EMPTY,EMPTY,EMPTY 
551 NORMAL,NORMAL,NORMAL 
552
553 BLUE,NORMAL,NORMAL
554 BLUE,RED,NORMAL 
555 CYAN,BLUE,NORMAL 
556 DCYAN,NORMAL,NORMAL
557 DCYAN,BLUE,NORMAL 
558 DGREEN,NORMAL,NORMAL 
559 DYELLOW,NORMAL,NORMAL 
560 GREEN,DGREEN,NORMAL 
561 GREEN,NORMAL,NORMAL 
562 MAGENTA,NORMAL,NORMAL
563 RED,NORMAL,NORMAL
564
565 BLACK,DGREY,NORMAL
566 DBLUE,DGREY,NORMAL 
567 DBLUE,DMAGENTA,NORMAL
568 DBLUE,DRED,NORMAL 
569 DBLUE,BLACK,NORMAL
570 DGREEN,DYELLOW,NORMAL 
571 DYELLOW,BLACK,NORMAL
572 DMAGENTA,BLACK,NORMAL
573 DCYAN,DBLUE,NORMAL
574
575 WHITE,GREY,NORMAL
576 GREY,WHITE,NORMAL
577 CYAN,GREY,NORMAL 
578 GREEN,WHITE,NORMAL 
579 GREEN,YELLOW,NORMAL 
580 YELLOW,WHITE,NORMAL 
581 MAGENTA,CYAN,NORMAL 
582 MAGENTA,YELLOW,NORMAL
583 RED,CYAN,NORMAL
584 RED,WHITE,NORMAL 
585 BLUE,WHITE,NORMAL
586 )
587
588 # WARNING: In the main part below (search for 'KONVI')
589 # there's a check for Konversation-specific config files.
590 # Any one of these can override the above if inxi is run
591 # from Konversation!
592
593 ## DISTRO DATA/ID ##
594 # In cases of derived distros where the version file of the base distro can also be found under /etc,
595 # the derived distro's version file should go first. (Such as with Sabayon / Gentoo)
596 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"
597 # debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu.
598 DISTROS_EXCLUDE_LIST="debian_version ubuntu_version"
599 DISTROS_PRIMARY="arch-release gentoo-release redhat-release slackware-version SuSE-release"
600 DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release"
601 # this is being used both by core distros and derived distros now, eg, solusos 1 uses it for solusos id, while
602 # debian, solusos base, uses it as well, so we have to know which it is.
603 DISTROS_OS_RELEASE_GOOD="arch-release SuSE-release"
604 ## Distros with known problems
605 # DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output
606 # Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially
607
608 ## OUTPUT FILTERS/SEARCH ##
609 # Note that \<ltd\> bans only words, not parts of strings; in \<corp\> you can't use punctuation characters like . or ,
610 # we're saving about 10+% of the total script exec time by hand building the ban lists here, using hard quotes.
611 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 ..\)'
612 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]'
613
614 SENSORS_GPU_SEARCH='intel|radeon|nouveau'
615
616 ### USB networking search string data, because some brands can have other products than
617 ### wifi/nic cards, they need further identifiers, with wildcards.
618 ### putting the most common and likely first, then the less common, then some specifics
619 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"
620 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" 
621 # then a few known hard to ID ones added 
622 # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; 
623 USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
624
625 ########################################################################
626 #### MAIN: Where it all begins
627 ########################################################################
628 main()
629 {
630         eval $LOGFS
631         
632         local color_scheme=''
633         # this will be used by all functions following
634         local Ps_aux_Data="$( ps aux )"
635
636         # This function just initializes variables
637         initialize_data
638         
639         # Source global config overrides, needs to be here because some things
640         # can be reset that were set in initialize, but check_required_apps needs
641         if [[ -s /etc/$SCRIPT_NAME.conf ]];then
642                 source /etc/$SCRIPT_NAME.conf
643         fi
644         # Source user config variables override /etc/inxi.conf variables
645         if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then
646                 source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf
647         fi
648         # Convert to new variable names if set in config files, legacy test
649         if [[ -n $LINE_MAX_CONSOLE ]];then
650                 COLS_MAX_CONSOLE=$LINE_MAX_CONSOLE
651         fi
652         if [[ -n $LINE_MAX_IRC ]];then
653                 COLS_MAX_IRC=$LINE_MAX_IRC
654         fi
655         # TERM_COLUMNS is set in top globals, using tput cols
656         if [[ $TERM_COLUMNS -lt $COLS_MAX_CONSOLE ]];then
657                 COLS_MAX_CONSOLE=$TERM_COLUMNS
658         fi
659         # adjust, some terminals will wrap if output cols == term cols
660         COLS_MAX_CONSOLE=$(( $COLS_MAX_CONSOLE - 2 ))
661         
662         # comes after source for user set stuff
663         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
664                 COLS_MAX=$COLS_MAX_CONSOLE
665                 SEP3=$SEP3_CONSOLE
666         else
667                 # too hard to read if no colors, so force that for users on irc
668                 if [[ $SCHEME == 0 ]];then
669                         SEP3=$SEP3_CONSOLE
670                 else
671                         SEP3=$SEP3_IRC
672                 fi
673                 COLS_MAX=$COLS_MAX_IRC
674         fi
675         COLS_INNER=$(( $COLS_MAX - $INDENT - 4 ))
676
677         # Check for dependencies BEFORE running ANYTHING else except above functions
678         # Not all distro's have these depends installed by default. Don't want to run
679         # this if the user is requesting to see this information in the first place
680         # Only continue if required apps tests ok
681         if [[ $1 != '--recommends' ]];then
682                 check_required_apps
683                 check_recommended_apps
684         fi
685
686         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
687         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
688         
689         # previous source location, check for bugs
690
691         ## this needs to run before the KONVI stuff is set below
692         ## Konversation 1.2 apparently does not like the $PPID test in get_start_client
693         ## So far there is no known way to detect if qt4_konvi is the parent process
694         ## this method will infer qt4_konvi as parent
695         get_start_client
696
697         # note: this only works if it's run from inside konversation as a script builtin or something
698         # only do this if inxi has been started as a konversation script, otherwise bypass this 
699 #       KONVI=3 ## for testing puroses
700         if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then
701                 if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3))    
702                         DCPORT="$1"
703                         DCSERVER="$2"
704                         DCTARGET="$3"
705                         shift 3
706                 elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4))
707                         DCSERVER="$1" ##dbus testing
708                         DCTARGET="$2" ##dbus testing
709                         shift 2
710                 fi
711
712                 # The section below is on request of Argonel from the Konversation developer team:
713                 # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
714                 IFS=":"
715                 for kde_config in $( kde-config --path data )
716                 do
717                         if [[ -r ${kde_config}${KONVI_CFG} ]];then
718                                 source "${kde_config}${KONVI_CFG}"
719                                 break
720                         fi
721                 done
722                 IFS="$ORIGINAL_IFS"
723         fi
724
725         ## leave this for debugging dcop stuff if we get that working
726         #       print_screen_output "DCPORT: $DCPORT"
727         #       print_screen_output "DCSERVER: $DCSERVER"
728         #       print_screen_output "DCTARGET: $DCTARGET"
729         
730         # first init function must be set first for colors etc. Remember, no debugger
731         # stuff works on this function unless you set the debugging flag manually.
732         # Debugging flag -@ [number] will not work until get_parameters runs.
733         
734         # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter.
735         # must be here to allow debugger and other flags to be set.
736         get_parameters "$@"
737
738         # If no colorscheme was set in the parameter handling routine, then set the default scheme
739         if [[ $B_COLOR_SCHEME_SET != 'true' ]];then
740                 # This let's user pick their color scheme. For IRC, only shows the color schemes, no interactive
741                 # The override value only will be placed in user config files. /etc/inxi.conf can also override
742                 if [[ $B_RUN_COLOR_SELECTOR == 'true' ]];then 
743                         select_default_color_scheme
744                 else
745                         # set the default, then override as required
746                         color_scheme=$DEFAULT_COLOR_SCHEME
747                         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
748                                 color_scheme=$GLOBAL_COLOR_SCHEME
749                         else
750                                 if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
751                                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
752                                                 color_scheme=$CONSOLE_COLOR_SCHEME
753                                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
754                                                 color_scheme=$VIRT_TERM_COLOR_SCHEME
755                                         fi
756                                 else
757                                         if [[ -n $IRC_X_TERM_COLOR_SCHEME && $B_CONSOLE_IRC == 'true' && -n $B_RUNNING_IN_DISPLAY ]];then
758                                                 color_scheme=$IRC_X_TERM_COLOR_SCHEME
759                                         elif [[ -n $IRC_CONS_COLOR_SCHEME && -z $DISPLAY ]];then
760                                                 color_scheme=$IRC_CONS_COLOR_SCHEME
761                                         elif [[ -n $IRC_COLOR_SCHEME ]];then
762                                                 color_scheme=$IRC_COLOR_SCHEME
763                                         fi
764                                 fi
765                         fi
766                         set_color_scheme $color_scheme
767                 fi
768         fi
769         
770         # all the pre-start stuff is in place now
771         B_SCRIPT_UP='true'
772         script_debugger "Debugger: $SCRIPT_NAME is up and running..."
773         
774         # then create the output
775         print_it_out
776
777         ## last steps
778         if [[ $B_RUNNING_IN_SHELL == 'true' && $SCHEME -gt 0 ]];then
779                 echo -n "\e[0m"
780         fi
781         eval $LOGFE
782         # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code
783         # from the last command is taken..
784         exit 0
785 }
786
787 #### -------------------------------------------------------------------
788 #### basic tests: set script data, booleans, PATH, version numbers
789 #### -------------------------------------------------------------------
790
791 # Set PATH data so we can access all programs as user. Set BAN lists.
792 # initialize some boleans, these directories are used throughout the script
793 # some apps are used for extended functions any directory used, should be
794 # checked here first.
795 # No args taken.
796 initialize_data()
797 {
798         eval $LOGFS
799         BSD_VERSION=$( uname -s 2>/dev/null | tr '[A-Z]' '[a-z]' )
800         
801         # note: archbsd says they are a freebsd distro, so assuming it's the same as freebsd
802         if [[ -n $( grep 'bsd' <<< "$BSD_VERSION" ) ]];then
803                 # GNU/kfreebsd will by definition have GNU tools like sed/grep
804                 if [[ -n $( grep 'kfreebsd' <<< "$BSD_VERSION" ) ]];then
805                         BSD_TYPE='debian-bsd' # debian gnu bsd
806                 else
807                         BSD_TYPE='bsd' # all other bsds
808                         SED_I="-i ''"
809                         SED_RX='-E'
810                 fi
811         fi
812         # now set the script BOOLEANS for files required to run features
813         # note that freebsd has /proc but it's empty
814         if [[ -d "/proc/" && -z $BSD_TYPE ]];then
815                 B_PROC_DIR='true'
816         elif [[ -n $BSD_TYPE ]];then
817                 B_PROC_DIR='false'
818         else
819                 error_handler 6
820         fi
821         
822         initialize_paths
823         
824         if [[ -n $BSD_TYPE ]];then
825                 if [[ -e $FILE_DMESG_BOOT ]];then
826                         B_DMESG_BOOT_FILE='true'
827                 fi
828         else
829                 # found a case of battery existing but having nothing in it on desktop mobo
830                 # not all laptops show the first, 
831                 if [[ -n $( ls /proc/acpi/battery 2>/dev/null ) ]];then
832                         B_PORTABLE='true'
833                 fi
834         fi
835         
836         
837         if [[ -e $FILE_CPUINFO ]]; then
838                 B_CPUINFO_FILE='true'
839         fi
840
841         if [[ -e $FILE_MEMINFO ]];then
842                 B_MEMINFO_FILE='true'
843         fi
844
845         if [[ -e $FILE_ASOUND_DEVICE ]];then
846                 B_ASOUND_DEVICE_FILE='true'
847         fi
848
849         if [[ -e $FILE_ASOUND_VERSION ]];then
850                 B_ASOUND_VERSION_FILE='true'
851         fi
852
853         if [[ -f $FILE_LSB_RELEASE ]];then
854                 B_LSB_FILE='true'
855         fi
856         
857         if [[ -f $FILE_OS_RELEASE ]];then
858                 B_OS_RELEASE_FILE='true'
859         fi
860
861         if [[ -e $FILE_SCSI ]];then
862                 B_SCSI_FILE='true'
863         fi
864
865         if [[ -n $DISPLAY ]];then
866                 B_SHOW_DISPLAY_DATA='true'
867                 B_RUNNING_IN_DISPLAY='true'
868         fi
869         
870         if [[ -e $FILE_MDSTAT ]];then
871                 B_MDSTAT_FILE='true'
872         fi
873
874         if [[ -e $FILE_MODULES ]];then
875                 B_MODULES_FILE='true'
876         fi
877
878         if [[ -e $FILE_MOUNTS ]];then
879                 B_MOUNTS_FILE='true'
880         fi
881
882         if [[ -e $FILE_PARTITIONS ]];then
883                 B_PARTITIONS_FILE='true'
884         fi
885         # default to the normal location, then search for it
886         if [[ -e $FILE_XORG_LOG ]];then
887                 B_XORG_LOG='true'
888         else
889                 # Detect location of the Xorg log file
890                 if [[ -n $( type -p xset ) ]]; then
891                         FILE_XORG_LOG=$( xset q 2>/dev/null | grep -i 'Log file' | gawk '{print $3}')
892                         if [[ -e $FILE_XORG_LOG ]];then
893                                 B_XORG_LOG='true'
894                         fi
895                 fi
896         fi
897         # gfx output will require this flag
898         if [[ $( whoami ) == 'root' ]];then
899                 B_ROOT='true'
900         fi
901         eval $LOGFE
902 }
903
904 # arg: $1 - version number: main/patch/date
905 parse_version_data()
906 {
907         local version_data=''
908
909         # note, using ####[[:space:]]+ to avoid having this function also trip the version datas
910         case $1 in
911                 date)
912                         version_data="$( gawk -F ': ' '
913                         /####[[:space:]]+Date:/ {
914                                 print $NF
915                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
916                         ;;
917                 main)
918                         version_data="$( gawk '
919                         /####[[:space:]]+Version:/ {
920                                 print $3
921                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
922                         ;;
923                 patch)
924                         version_data="$( gawk '
925                         /####[[:space:]]+Patch Number:/ {
926                                 print $4
927                         }' $SCRIPT_PATH/$SCRIPT_NAME )"
928                         ;;
929         esac
930         echo $version_data
931 }
932
933 initialize_paths()
934 {
935         local path='' added_path='' b_path_found='' sys_path=''
936         # Extra path variable to make execute failures less likely, merged below
937         local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
938         
939         # this needs to be set here because various options call the parent initialize function directly.
940         SCRIPT_PATH=$( dirname $0 )
941
942         # Fallback paths put into $extra_paths; This might, among others, help on gentoo.
943         # Now, create a difference of $PATH and $extra_paths and add that to $PATH:
944         IFS=":"
945         for path in $extra_paths
946         do
947                 b_path_found='false'
948                 for sys_path in $PATH
949                 do
950                         if [[ $path == $sys_path ]];then
951                                 b_path_found='true'
952                         fi
953                 done
954                 if [[ $b_path_found == 'false' ]];then
955                         added_path="$added_path:$path"
956                 fi
957         done
958
959         IFS="$ORIGINAL_IFS"
960         PATH="${PATH}${added_path}"
961         ##echo "PATH='$PATH'"
962         ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""'
963 }
964
965 # No args taken.
966 check_recommended_apps()
967 {
968         eval $LOGFS
969         local bash_array_test=( "one" "two" )
970
971         # check for array ability of bash, this is only good for the warning at this time
972         # the boolean could be used later
973         # bash version 2.05b is used in DSL
974         # bash version 3.0 is used in Puppy Linux; it has a known array bug <reference to be placed here>
975         # versions older than 3.1 don't handle arrays
976         # distro's using below 2.05b are unknown, released in 2002
977         if [[ ${bash_array_test[1]} -eq "two" ]];then
978                 B_BASH_ARRAY='true'
979         else
980                 script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output"
981         fi
982         # test for a few apps that bsds may not have after initial tests
983         if [[ -n $( type -p lspci ) ]];then
984                 B_LSPCI='true'
985         fi
986         if [[ -n $BSD_TYPE ]];then
987                 if [[ -n $( type -p sysctl ) ]];then
988                         B_SYSCTL='true'
989                 fi
990                 if [[ -n $( type -p pciconf ) ]];then
991                         B_PCICONF='true'
992                 fi
993         fi
994         # now setting qdbus/dcop for first run, some systems can have both by the way
995         if [[ -n $( type -p qdbus ) ]];then
996                 B_QDBUS='true'
997         fi
998         if [[ -n $( type -p dcop ) ]];then
999                 B_DCOP='true'
1000         fi
1001         eval $LOGFE
1002 }
1003
1004 # Determine if any of the absolutely necessary tools are absent
1005 # No args taken.
1006 check_required_apps()
1007 {
1008         eval $LOGFS
1009         local app_name='' app_path=''
1010         # bc removed from deps for now
1011         local depends="df gawk grep ps readlink tr uname uptime wc"
1012         
1013         if [[ -z $BSD_TYPE  ]];then
1014                 depends="$depends lspci"
1015         elif [[ $BSD_TYPE == 'bsd' ]];then
1016                 depends="$depends sysctl"
1017                 # debian-bsd has lspci but you must be root to run it
1018         elif [[ $BSD_TYPE == 'debian-bsd' ]];then
1019                 depends="$depends sysctl lspci"
1020         fi
1021         # no need to add xprop because it will just give N/A if not there, but if we expand use of xprop,
1022         # should add that here as a test, then use the B_SHOW_DISPLAY_DATA flag to trigger the tests in de function
1023         local x_apps="xrandr xdpyinfo glxinfo" 
1024
1025         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
1026                 for app_name in $x_apps
1027                 do
1028                         app_path=$( type -p $app_name )
1029                         if [[ -z $app_path ]];then
1030                                 script_debugger "Resuming in non X mode: $app_name not found. For package install advice run: $SCRIPT_NAME --recommends"
1031                                 B_SHOW_DISPLAY_DATA='false'
1032                                 break
1033                         fi
1034                 done
1035         fi
1036
1037         app_name=''
1038
1039         for app_name in $depends
1040         do
1041                 app_path=$( type -p $app_name )
1042                 if [[ -z $app_path ]];then
1043                         error_handler 5 "$app_name"
1044                 fi
1045         done
1046         eval $LOGFE
1047 }
1048
1049 ## note: this is now running inside each gawk sequence directly to avoid exiting gawk
1050 ## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array
1051 ## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods
1052 # Enforce boilerplate and buzzword filters
1053 # args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize
1054 sanitize_characters()
1055 {
1056         eval $LOGFS
1057         # Cannot use strong quotes to unquote a string with pipes in it!
1058         # bash will interpret the |'s as usual and try to run a subshell!
1059         # Using weak quotes instead, or use '"..."'
1060         echo "$2" | gawk "
1061         BEGIN {
1062                 IGNORECASE=1
1063         }
1064         {
1065                 gsub(/${!1}/,\"\")
1066                 gsub(/ [ ]+/,\" \")    ## ([ ]+) with (space)
1067                 gsub(/^ +| +$/,\"\")   ## (pipe char) with (nothing)
1068                 print                  ## prints (returns) cleaned input
1069         }"
1070         eval $LOGFE
1071 }
1072
1073 # Set the colorscheme
1074 # args: $1 = <scheme number>|<"none">
1075 set_color_scheme()
1076 {
1077         eval $LOGFS
1078         local i='' a_output_colors='' a_color_codes=''
1079
1080         if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then
1081                 set -- 1
1082         fi
1083         # Set a global variable to allow checking for chosen scheme later
1084         SCHEME="$1"
1085         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1086                 a_color_codes=( $ANSI_COLORS )
1087         else
1088                 a_color_codes=( $IRC_COLORS )
1089         fi
1090         for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ ))
1091         do
1092                 eval "${A_COLORS_AVAILABLE[i]}=\"${a_color_codes[i]}\""
1093         done
1094         IFS=","
1095         a_output_colors=( ${A_COLOR_SCHEMES[$1]} )
1096         IFS="$ORIGINAL_IFS"
1097         # then assign the colors globally
1098         C1="${!a_output_colors[0]}"
1099         C2="${!a_output_colors[1]}"
1100         CN="${!a_output_colors[2]}"
1101         # ((COLOR_SCHEME++)) ## note: why is this? ##
1102         eval $LOGFE
1103 }
1104
1105 select_default_color_scheme()
1106 {
1107         eval $LOGFS
1108         local spacer='  ' options='' user_selection='' config_variable=''
1109         local config_file="$HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf"
1110         local irc_clear="\e[0m" 
1111         local irc_gui='Unset' irc_console='Unset' irc_x_term='Unset'
1112         local console='Unset' virt_term='Unset' global='Unset' 
1113         
1114         if [[ -n $IRC_COLOR_SCHEME ]];then
1115                 irc_gui="Set: $IRC_COLOR_SCHEME"
1116         fi
1117         if [[ -n $IRC_CONS_COLOR_SCHEME ]];then
1118                 irc_console="Set: $IRC_CONS_COLOR_SCHEME"
1119         fi
1120         if [[ -n $IRC_X_TERM_COLOR_SCHEME ]];then
1121                 irc_x_term="Set: $IRC_X_TERM_COLOR_SCHEME"
1122         fi
1123         if [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1124                 virt_term="Set: $VIRT_TERM_COLOR_SCHEME"
1125         fi
1126         if [[ -n $CONSOLE_COLOR_SCHEME ]];then
1127                 console="Set: $CONSOLE_COLOR_SCHEME"
1128         fi
1129         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
1130                 global="Set: $GLOBAL_COLOR_SCHEME"
1131         fi
1132         
1133         # don't want these printing in irc since they show literally
1134         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1135                 irc_clear=''
1136         fi
1137         # first make output neutral so it's just plain default for console client
1138         set_color_scheme "0"
1139         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1140                 print_screen_output "Welcome to $SCRIPT_NAME! Please select the default $COLOR_SELECTION color scheme."
1141                 # print_screen_output "You will see this message only one time per user account, unless you set preferences in: /etc/$SCRIPT_NAME.conf"
1142                 print_screen_output " "
1143         fi
1144         print_screen_output "Because there is no way to know your $COLOR_SELECTION foreground/background colors, you can"
1145         print_screen_output "set your color preferences from color scheme option list below. 0 is no colors, 1 neutral."
1146         print_screen_output "After these, there are 3 sets: 1-dark or light backgrounds; 2-light backgrounds; 3-dark backgrounds."
1147         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1148                 print_screen_output "Please note that this will set the $COLOR_SELECTION preferences only for user: $(whoami)"
1149         fi
1150         print_screen_output "------------------------------------------------------------------------------"
1151         for (( i=0; i < ${#A_COLOR_SCHEMES[@]}; i++ ))
1152         do
1153                 if [[ $i -gt 9 ]];then
1154                         spacer=' '
1155                 fi
1156                 # only offer the safe universal defaults
1157                 case $COLOR_SELECTION in
1158                         global|irc|irc-console|irc-virtual-terminal)
1159                                 if [[ $i -gt $SAFE_COLOR_COUNT ]];then
1160                                         break
1161                                 fi
1162                                 ;;
1163                 esac
1164                 set_color_scheme $i
1165                 print_screen_output "$irc_clear $i)$spacer${C1}Card:${C2} nVidia G86 [GeForce 8400 GS] ${C1}X.Org${C2} 1.7.7"
1166         done
1167         set_color_scheme 0
1168         
1169         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1170                 echo -n "\e[0m"
1171                 print_screen_output "$irc_clear $i)${spacer}Remove all color settings. Restore $SCRIPT_NAME default."
1172                 print_screen_output "$irc_clear $(($i+1)))${spacer}Continue, no changes or config file setting."
1173                 print_screen_output "$irc_clear $(($i+2)))${spacer}Exit, use another terminal, or set manually."
1174                 print_screen_output "------------------------------------------------------------------------------"
1175                 print_screen_output "Simply type the number for the color scheme that looks best to your eyes for your $COLOR_SELECTION settings"
1176                 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:"
1177                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1178                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1179                 print_screen_output "Your selection(s) will be stored here: $config_file"
1180                 print_screen_output "Global overrides all individual color schemes. Individual schemes remove the global setting."
1181                 print_screen_output "------------------------------------------------------------------------------"
1182                 read user_selection
1183                 if [[ -n $( grep -Es '^([0-9]+)$' <<< "$user_selection" ) && $user_selection -lt $i ]];then
1184                         case $COLOR_SELECTION in
1185                                 irc)
1186                                         config_variable='IRC_COLOR_SCHEME'
1187                                         ;;
1188                                 irc-console)
1189                                         config_variable='IRC_CONS_COLOR_SCHEME'
1190                                         ;;
1191                                 irc-virtual-terminal)
1192                                         config_variable='IRC_X_TERM_COLOR_SCHEME'
1193                                         ;;
1194                                 console)
1195                                         config_variable='CONSOLE_COLOR_SCHEME'
1196                                         ;;
1197                                 virtual-terminal)
1198                                         config_variable='VIRT_TERM_COLOR_SCHEME'
1199                                         ;;
1200                                 global)
1201                                         config_variable='GLOBAL_COLOR_SCHEME'
1202                                         ;;
1203                         esac
1204                         set_color_scheme $user_selection
1205                         # make file/directory first if missing
1206                         if [[ ! -f $config_file ]];then
1207                                 if [[ ! -d $HOME/.$SCRIPT_NAME ]];then
1208                                         mkdir $HOME/.$SCRIPT_NAME
1209                                 fi
1210                                 touch $config_file
1211                         fi
1212                         if [[ -z $( grep -s "$config_variable=" $config_file ) ]];then
1213                                 print_screen_output "Creating and updating config file for $COLOR_SELECTION color scheme now..."
1214                                 echo "$config_variable=$user_selection" >> $config_file
1215                         else
1216                                 print_screen_output "Updating config file for $COLOR_SELECTION color scheme now..."
1217                                 sed $SED_I "s/$config_variable=.*/$config_variable=$user_selection/" $config_file
1218                         fi
1219                         # file exists now so we can go on to cleanup
1220                         case $COLOR_SELECTION in
1221                                 irc|irc-console|irc-virtual-terminal|console|virtual-terminal)
1222                                         sed $SED_I '/GLOBAL_COLOR_SCHEME=/d' $config_file
1223                                         ;;
1224                                 global)
1225                                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' -e '/IRC_COLOR_SCHEME=/d' \
1226                                         -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1227                                         ;;
1228                         esac
1229                 elif [[ $user_selection == $i ]];then
1230                         print_screen_output "Removing all color settings from config file now..."
1231                         sed $SED_I -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/GLOBAL_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' \
1232                         -e '/IRC_COLOR_SCHEME=/d' -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1233                         set_color_scheme $DEFAULT_COLOR_SCHEME
1234                 elif [[ $user_selection == $(( $i+1 )) ]];then
1235                         print_screen_output "Ok, continuing $SCRIPT_NAME unchanged. You can set the colors anytime by starting with: -c 95 to 99"
1236                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
1237                                 set_color_scheme $CONSOLE_COLOR_SCHEME
1238                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1239                                 set_color_scheme $VIRT_TERM_COLOR_SCHEME
1240                         else
1241                                 set_color_scheme $DEFAULT_COLOR_SCHEME
1242                         fi
1243                 elif [[ $user_selection == $(( $i+2 )) ]];then
1244                         set_color_scheme $DEFAULT_COLOR_SCHEME
1245                         print_screen_output "Ok, exiting $SCRIPT_NAME now. You can set the colors later."
1246                         exit 0
1247                 else
1248                         print_screen_output "Error - Invalid Selection. You entered this: $user_selection"
1249                         print_screen_output " "
1250                         select_default_color_scheme
1251                 fi
1252         else
1253                 print_screen_output "------------------------------------------------------------------------------"
1254                 print_screen_output "After finding the scheme number you like, simply run this again in a terminal to set the configuration"
1255                 print_screen_output "data file for your irc client. You can set color schemes for the following: start inxi with -c plus:"
1256                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1257                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1258                 exit 0
1259         fi
1260
1261         eval $LOGFE
1262 }
1263
1264 ########################################################################
1265 #### UTILITY FUNCTIONS
1266 ########################################################################
1267
1268 #### -------------------------------------------------------------------
1269 #### error handler, debugger, script updater
1270 #### -------------------------------------------------------------------
1271
1272 # Error handling
1273 # args: $1 - error number; $2 - optional, extra information; $3 - optional extra info
1274 error_handler()
1275 {
1276         eval $LOGFS
1277         local error_message=''
1278
1279         # assemble the error message
1280         case $1 in
1281                 2)      error_message="large flood danger, debug buffer full!"
1282                         ;;
1283                 3)      error_message="unsupported color scheme number: $2"
1284                         ;;
1285                 4)      error_message="unsupported verbosity level: $2"
1286                         ;;
1287                 5)      error_message="dependency not met: $2 not found in path.\nFor distribution installation package names and missing apps information, run: $SCRIPT_NAME --recommends"
1288                         ;;
1289                 6)      error_message="/proc not found! Quitting..."
1290                         ;;
1291                 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"
1292                         ;;
1293                 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"
1294                         ;;
1295                 9)      error_message="unsupported debugging level: $2"
1296                         ;;
1297                 10)
1298                         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/"
1299                         ;;
1300                 11)
1301                         error_message="unsupported testing option argument: -! $2"
1302                         ;;
1303                 12)
1304                         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."
1305                         ;;
1306                 13)
1307                         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"
1308                         ;;
1309                 14)
1310                         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"
1311                         ;;
1312                 15)
1313                         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"
1314                         ;;
1315                 16)
1316                         error_message="$SCRIPT_NAME downloaded but the file data is corrupted. Purged data and using current version."
1317                         ;;
1318                 17)
1319                         error_message="All $SCRIPT_NAME self updater features have been disabled by the distribution\npackage maintainer. This includes the option you used: $2"
1320                         ;;
1321                 18)
1322                         error_message="The argument you provided for $2 does not have supported syntax.\nPlease use the following formatting:\n$3"
1323                         ;;
1324                 19)
1325                         error_message="The option $2 has been deprecated. Please use $3 instead.\nSee -h for instructions and syntax."
1326                         ;;
1327                 20)
1328                         error_message="The option you selected has been deprecated. $2\nSee the -h (help) menu for currently supported options."
1329                         ;;
1330                 *)      error_message="error unknown: $@"
1331                         set -- 99
1332                         ;;
1333         esac
1334         # then print it and exit
1335         print_screen_output "Error $1: $error_message"
1336         eval $LOGFE
1337         exit $1
1338 }
1339
1340 # prior to script up set, pack the data into an array
1341 # then we'll print it out later.
1342 # args: $1 - $@ debugging string text
1343 script_debugger()
1344 {
1345         eval $LOGFS
1346         if [[ $B_SCRIPT_UP == 'true' ]];then
1347                 # only return if debugger is off and no pre start up errors have occured
1348                 if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then
1349                         return 0
1350                 # print out the stored debugging information if errors occured
1351                 elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then
1352                         for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ ))
1353                         do
1354                                 print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}"
1355                         done
1356                         DEBUG_BUFFER_INDEX=0
1357                 fi
1358                 # or print out normal debugger messages if debugger is on
1359                 if [[ $DEBUG -gt 0 ]];then
1360                         print_screen_output "$1"
1361                 fi
1362         else
1363                 if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then
1364                         error_handler 2
1365                 # this case stores the data for later printout, will print out only
1366                 # at B_SCRIPT_UP == 'true' if array index > 0
1367                 else
1368                         A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1"
1369                         # increment count for next pre script up debugging error
1370                         (( DEBUG_BUFFER_INDEX++ ))
1371                 fi
1372         fi
1373         eval $LOGFE
1374 }
1375
1376 # NOTE: no logging available until get_parameters is run, since that's what sets logging
1377 # in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables.
1378 # $1 alone: logs data; $2 with or without $3 logs func start/end.
1379 # $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]]
1380 log_function_data()
1381 {
1382         if [ "$B_USE_LOGGING" == 'true' ];then
1383                 local logged_data='' spacer='   ' line='----------------------------------------'
1384                 case $1 in
1385                         fs)
1386                                 logged_data="Function: $2 - Primary: Start"
1387                                 if [ -n "$3" ];then
1388                                         logged_data="$logged_data\n${spacer}Args: $3"
1389                                 fi
1390                                 spacer=''
1391                                 ;;
1392                         fe)
1393                                 logged_data="Function: $2 - Primary: End"
1394                                 spacer=''
1395                                 ;;
1396                         cat)
1397                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1398                                         logged_data="\n$line\nFull file data: cat $2\n\n$( cat $2 )\n$line\n"
1399                                         spacer=''
1400                                 fi
1401                                 ;;
1402                         raw)
1403                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1404                                         logged_data="\n$line\nRaw system data:\n\n$2\n$line\n"
1405                                         spacer=''
1406                                 fi
1407                                 ;;
1408                         *)
1409                                 logged_data="$1"
1410                                 ;;
1411                 esac
1412                 # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2).
1413                 # This pattern doesn't work for irc colors, if we need that someone can figure it out
1414                 if [[ -n $logged_data ]];then
1415                         if [[ $B_LOG_COLORS != 'true' ]];then
1416                                 echo -e "${spacer}$logged_data" | sed $SED_RX 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE
1417                         else
1418                                 echo -e "${spacer}$logged_data" >> $LOG_FILE
1419                         fi
1420                 fi
1421         fi
1422 }
1423
1424 # called in the initial -@ 10 script args setting so we can get logging as soon as possible
1425 # will have max 3 files, inxi.log, inxi.1.log, inxi.2.log
1426 create_rotate_logfiles()
1427 {
1428         if [[ ! -d $SCRIPT_DATA_DIR ]];then
1429                 mkdir $SCRIPT_DATA_DIR
1430         fi
1431         # do the rotation if logfile exists
1432         if [[ -f $LOG_FILE ]];then
1433                 # copy if present second to third
1434                 if [[ -f $LOG_FILE_1 ]];then
1435                         mv -f $LOG_FILE_1 $LOG_FILE_2
1436                 fi
1437                 # then copy initial to second
1438                 mv -f $LOG_FILE $LOG_FILE_1
1439         fi
1440         # now create the logfile
1441         touch $LOG_FILE
1442         # and echo the start data
1443         echo "=========================================================" >> $LOG_FILE
1444         echo "START $SCRIPT_NAME LOGGING:"                               >> $LOG_FILE
1445         echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )"              >> $LOG_FILE
1446         echo "=========================================================" >> $LOG_FILE
1447 }
1448
1449 # args: $1 - download url, not including file name; $2 - string to print out
1450 # $3 - update type option
1451 # note that $1 must end in / to properly construct the url path
1452 script_self_updater()
1453 {
1454         eval $LOGFS
1455         local wget_error=0 file_contents='' wget_man_error=0 
1456         local man_file_path="$MAN_FILE_LOCATION/inxi.1.gz"
1457         
1458         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1459                 print_screen_output "Sorry, you can't run the $SCRIPT_NAME self updater option (-$3) in an IRC client."
1460                 exit 1
1461         fi
1462
1463         print_screen_output "Starting $SCRIPT_NAME self updater."
1464         print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER"
1465         print_screen_output "Current version patch number: $SCRIPT_PATCH_NUMBER"
1466         print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..."
1467
1468         file_contents="$( wget -q -O - $1$SCRIPT_NAME )" || wget_error=$?
1469         # then do the actual download
1470         if [[  $wget_error -eq 0 ]];then
1471                 # make sure the whole file got downloaded and is in the variable
1472                 if [[ -n $( grep '###\*\*EOF\*\*###' <<< "$file_contents" ) ]];then
1473                         echo "$file_contents" > $SCRIPT_PATH/$SCRIPT_NAME || error_handler 14 "$?"
1474                         chmod +x $SCRIPT_PATH/$SCRIPT_NAME || error_handler 15 "$?"
1475                         SCRIPT_VERSION_NUMBER=$( parse_version_data 'main' )
1476                         SCRIPT_PATCH_NUMBER=$( parse_version_data 'patch' )
1477                         print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER"
1478                         print_screen_output "New $2 version patch number: $SCRIPT_PATCH_NUMBER"
1479                         print_screen_output "To run the new version, just start $SCRIPT_NAME again."
1480                         print_screen_output "----------------------------------------"
1481                         print_screen_output "Starting download of man page file now."
1482                         if [[ ! -d $MAN_FILE_LOCATION ]];then
1483                                 print_screen_output "The required man directory was not detected on your system, unable to continue: $MAN_FILE_LOCATION"
1484                         else
1485                                 if [[ $B_ROOT == 'true' ]];then
1486                                         print_screen_output "Checking Man page download URL..."
1487                                         if [[ -f /usr/share/man/man8/inxi.8.gz ]];then
1488                                                 print_screen_output "Updating man page location to man1."
1489                                                 mv -f /usr/share/man/man8/inxi.8.gz /usr/share/man/man1/inxi.1.gz 
1490                                                 if [[ -n $( type -p mandb ) ]];then
1491                                                         exec $( type -p mandb ) -q 
1492                                                 fi
1493                                         fi
1494                                         wget -q --spider $MAN_FILE_DOWNLOAD || wget_man_error=$?
1495                                         if [[ $wget_man_error -eq 0 ]];then
1496                                                 print_screen_output "Man file download URL verified: $MAN_FILE_DOWNLOAD"
1497                                                 print_screen_output "Downloading Man page file now."
1498                                                 wget -q -O $man_file_path $MAN_FILE_DOWNLOAD || wget_man_error=$?
1499                                                 if [[ $wget_man_error -gt 0 ]];then
1500                                                         print_screen_output "Oh no! Something went wrong downloading the Man gz file at: $MAN_FILE_DOWNLOAD"
1501                                                         print_screen_output "Check the error messages for what happened. Error: $wget_man_error"
1502                                                 else
1503                                                         print_screen_output "Download/install of man page successful. Check to make sure it works: man inxi"
1504                                                 fi
1505                                         else
1506                                                 print_screen_output "Man file download URL failed, unable to continue: $MAN_FILE_DOWNLOAD"
1507                                         fi
1508                                 else
1509                                         print_screen_output "Updating / Installing the Man page requires root user, writing to: $MAN_FILE_LOCATION"
1510                                         print_screen_output "If you want the man page, you'll have to run $SCRIPT_NAME -$3 as root."
1511                                 fi
1512                         fi
1513                         exit 0
1514                 else
1515                         error_handler 16
1516                 fi
1517         # now run the error handlers on any wget failure
1518         else
1519                 if [[ $2 == 'svn server' ]];then
1520                         error_handler 8 "$wget_error"
1521                 elif [[ $2 == 'alt server' ]];then
1522                         error_handler 10 "$1"
1523                 else
1524                         error_handler 12 "$1"
1525                 fi
1526         fi
1527         eval $LOGFS
1528 }
1529
1530 # args: $1 - debug data type: sys|xorg|disk
1531 debug_data_collector()
1532 {
1533         local xiin_app='' xiin_data_file='' xiin_download='' error='' b_run_xiin='false'
1534         local debug_data_dir='' bsd_string=''
1535         local completed_gz_file='' xiin_file='xiin.py' ftp_upload='ftp.techpatterns.com/incoming'
1536         local Line='-------------------------'
1537         local start_directory=$( pwd )
1538         
1539         if [[ -n $BSD_TYPE ]];then
1540                 bsd_string="$BSD_TYPE-"
1541         fi
1542         
1543         debug_data_dir="inxi-$bsd_string$(tr ' ' '-' <<< $HOSTNAME | tr '[A-Z]' '[a-z]' )-$1-$(date +%Y%m%d)" 
1544         
1545         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1546                 if [[ -n $ALTERNATE_FTP ]];then
1547                         ftp_upload=$ALTERNATE_FTP
1548                 fi
1549                 echo "Starting debugging data collection type: $1"
1550                 echo -n "Checking/creating required directories... "
1551                 if [[ ! -d $SCRIPT_DATA_DIR ]];then
1552                         mkdir $SCRIPT_DATA_DIR
1553                 fi
1554                 echo 'completed'
1555                 cd $SCRIPT_DATA_DIR
1556                 if [[ -d $SCRIPT_DATA_DIR/$debug_data_dir ]];then
1557                         echo 'Deleting previous xiin data directory...'
1558                         rm -rf $SCRIPT_DATA_DIR/$debug_data_dir
1559                 fi
1560                 mkdir $SCRIPT_DATA_DIR/$debug_data_dir
1561                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
1562                         echo 'Deleting previous tar.gz file...'
1563                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1564                 fi
1565                 
1566                 echo 'Collecting system info: sensors, lsusb, lspci, lspci -v data, plus /proc data'
1567                 echo 'also checking for dmidecode data: note, you must be root to have dmidecode work.'
1568                 echo "Data going into: $SCRIPT_DATA_DIR/$debug_data_dir"
1569                 # bsd tools
1570                 pciconf -vl &> $debug_data_dir/bsd-pciconf-vl.txt
1571                 sysctl -a &> $debug_data_dir/bsd-sysctl-a.txt
1572                 
1573                 dmidecode &> $debug_data_dir/dmidecode.txt
1574                 
1575                 lscpu &> $debug_data_dir/lscpu.txt
1576                 lspci &> $debug_data_dir/lspci.txt
1577                 lspci -n &> $debug_data_dir/lspci-n.txt
1578                 lspci -v &> $debug_data_dir/lspci-v.txt
1579                 lsusb &> $debug_data_dir/lsusb.txt
1580                 ps aux &> $debug_data_dir/ps-aux.txt
1581                 runlevel &> $debug_data_dir/runlevel.txt
1582                 systemctl list-units &> $debug_data_dir/systemctl-list-units.txt
1583                 systemctl list-units --type=target &> $debug_data_dir/systemctl-list-units-target.txt
1584                 initctl list &> $debug_data_dir/initctl-list.txt
1585                 sensors &> $debug_data_dir/sensors.txt
1586                 strings --version  &> $debug_data_dir/strings.txt
1587                 nvidia-smi -q &> $debug_data_dir/nvidia-smi-q.txt
1588                 nvidia-smi -q -x &> $debug_data_dir/nvidia-smi-xq.txt
1589                 
1590                 ls /usr/bin/gcc* &> $debug_data_dir/gcc-sys-versions.txt
1591                 gcc --version &> $debug_data_dir/gcc-version.txt
1592                 cat /etc/issue &> $debug_data_dir/etc-issue.txt
1593                 cat $FILE_LSB_RELEASE &> $debug_data_dir/lsb-release.txt
1594                 cat $FILE_OS_RELEASE &> $debug_data_dir/os-release.txt
1595                 cat $FILE_ASOUND_DEVICE &> $debug_data_dir/proc-asound-device.txt
1596                 cat $FILE_ASOUND_VERSION &> $debug_data_dir/proc-asound-version.txt
1597                 cat $FILE_CPUINFO &> $debug_data_dir/proc-cpu-info.txt
1598                 cat $FILE_MEMINFO &> $debug_data_dir/proc-meminfo.txt
1599                 cat $FILE_MODULES &> $debug_data_dir/proc-modules.txt
1600                 cat /proc/net/arp &> $debug_data_dir/proc-net-arp.txt 
1601                 # bsd data
1602                 cat /var/run/dmesg.boot &> $debug_data_dir/bsd-var-run-dmesg.boot.txt 
1603                 
1604                 check_recommends_user_output &> $debug_data_dir/check-recommends-user-output.txt
1605                 # first download and verify xiin
1606                 if [[ $B_UPLOAD_DEBUG_DATA == 'true' || $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1607                         touch $SCRIPT_DATA_DIR/$debug_data_dir/xiin-error.txt
1608                         echo "Downloading required tree traverse tool $xiin_file..."
1609                         if [[ -f xiin && ! -f $xiin_file ]];then
1610                                 mv -f xiin $xiin_file
1611                         fi
1612                         # -Nc is creating really weird download anomolies, so using -O instead
1613                         xiin_download="$( wget -q -O - http://inxi.googlecode.com/svn/branches/xiin/$xiin_file )"
1614                         # if nothing got downloaded kick out error, otherwise we'll use an older version
1615                         if [[ $? -gt 0 && ! -f $xiin_file ]];then
1616                                 echo -e "ERROR: Failed to download required file: $xiin_file\nMaybe the remote site is down or your networking is broken?"
1617                                 echo "Continuing with incomplete data collection."
1618                                 echo "$xiin_file download failed and no existing $xiin_file" >> $debug_data_dir/xiin-error.txt
1619                         elif [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) || -f $xiin_file ]];then
1620                                 if [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) ]];then
1621                                         echo "Updating $xiin_file from remote location"
1622                                         echo "$xiin_download" > $xiin_file
1623                                 else
1624                                         echo "Using local $xiin_file due to download failure"
1625                                 fi
1626                                 b_run_xiin='true'
1627                         else
1628                                 echo -e "ERROR: $xiin_file downloaded but the program file data is corrupted.\nContinuing with incomplete data collection."
1629                                 echo "$xiin_file downloaded but the program file data is corrupted." >> $debug_data_dir/xiin-error.txt
1630                         fi
1631                 fi
1632                 # note, only bash 4> supports ;;& for case, so using if/then here
1633                 if [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1634                         xiin_data_file=$SCRIPT_DATA_DIR/$debug_data_dir/xiin-sys.txt
1635                         echo 'Collecting networking data...'
1636                         ifconfig &> $debug_data_dir/ifconfig.txt
1637                         ip addr &> $debug_data_dir/ip-addr.txt
1638                         if [[ $b_run_xiin == 'true' && -z $BSD_TYPE ]];then
1639                                 echo $Line
1640                                 echo "Running $xiin_file tool now on /sys..."
1641                                 echo "Using Python version:" && python --version
1642                                 python --version &> $debug_data_dir/python-version.txt
1643                                 python ./$xiin_file -d /sys -f $xiin_data_file
1644                                 if [[ $? -ne 0 ]];then
1645                                         error=$?
1646                                         echo -e "ERROR: $xiin_file exited with error $error - removing data file.\nContinuing with incomplete data collection."
1647                                         echo "Continuing with incomplete data collection."
1648                                         rm -f $xiin_data_file
1649                                         echo "$xiin_file data generation failed with python error $error" >> $debug_data_dir/xiin-error.txt
1650                                 fi
1651                                 echo $Line
1652                         fi
1653                 fi
1654                 if [[ $1 == 'xorg' || $1 == 'all' ]];then
1655                         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
1656                                 echo 'Warning: only some of the data collection can occur if you are not in X'
1657                                 touch $debug_data_dir/warning-user-not-in-x
1658                         fi
1659                         if [[ $B_ROOT == 'true' ]];then
1660                                 echo 'Warning: only some of the data collection can occur if you are running as Root user'
1661                                 touch $debug_data_dir/warning-root-user
1662                         fi
1663                         echo 'Collecting Xorg log and xorg.conf files'
1664                         if [[ -e $FILE_XORG_LOG ]];then
1665                                 cat $FILE_XORG_LOG &> $debug_data_dir/xorg-log-file.txt
1666                         else
1667                                 touch $debug_data_dir/no-xorg-log-file
1668                         fi
1669                         if [[ -e /etc/X11/xorg.conf ]];then
1670                                 cp /etc/X11/xorg.conf $SCRIPT_DATA_DIR/$debug_data_dir
1671                         else
1672                                 touch $debug_data_dir/no-xorg-conf-file
1673                         fi
1674                         if [[ -n $( ls /etc/X11/xorg.conf.d/ 2>/dev/null ) ]];then
1675                                 ls /etc/X11/xorg.conf.d &> $debug_data_dir/ls-etc-x11-xorg-conf-d.txt
1676                                 cp /etc/X11/xorg.conf.d $SCRIPT_DATA_DIR/$debug_data_dir
1677                         else
1678                                 touch $debug_data_dir/no-xorg-conf-d-files
1679                         fi
1680                         echo 'Collecting X, xprop, glxinfo, xrandr, xdpyinfo data...'
1681                         xprop -root &> $debug_data_dir/xprop_root.txt
1682                         glxinfo &> $debug_data_dir/glxinfo.txt
1683                         xdpyinfo &> $debug_data_dir/xdpyinfo.txt
1684                         xrandr &> $debug_data_dir/xrandr.txt
1685                         X -version &> $debug_data_dir/x-version.txt
1686                         Xorg -version &> $debug_data_dir/xorg-version.txt
1687                         echo $GNOME_DESKTOP_SESSION_ID &> $debug_data_dir/gnome-desktop-session-id.txt
1688                         # kde 3 id
1689                         echo $KDE_FULL_SESSION &> $debug_data_dir/kde3-ful-session.txt
1690                         echo $KDE_SESSION_VERSION &> $debug_data_dir/kde456-session-version.txt
1691                         echo "$(kded$KDE_SESSION_VERSION --version )" &> $debug_data_dir/kde-version-data.txt
1692                         echo $XDG_CURRENT_DESKTOP &> $debug_data_dir/xdg-current-desktop.txt
1693                 fi
1694                 if [[ $1 == 'disk' || $1 == 'all' ]];then
1695                         echo 'Collecting dev, label, disk, uuid data, df...'
1696                         ls -l /dev &> $debug_data_dir/dev-data.txt
1697                         ls -l /dev/disk &> $debug_data_dir/dev-disk-data.txt
1698                         ls -l /dev/disk/by-id &> $debug_data_dir/dev-disk-id-data.txt
1699                         ls -l /dev/disk/by-label &> $debug_data_dir/dev-disk-label-data.txt
1700                         ls -l /dev/disk/by-uuid &> $debug_data_dir/dev-disk-uuid-data.txt
1701                         ls -l /dev/disk/by-path &> $debug_data_dir/dev-disk-path-data.txt
1702                         ls -l /dev/mapper &> $debug_data_dir/dev-disk-mapper-data.txt
1703                         readlink /dev/root &> $debug_data_dir/dev-root.txt
1704                         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
1705                         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
1706                         df -H -T &> $debug_data_dir/bsd-df-H-T-no-excludes.txt
1707                         df -H &> $debug_data_dir/bsd-df-H-no-excludes.txt
1708                         # bsd tool
1709                         mount &> $debug_data_dir/mount.txt
1710                         gpart list &> $debug_data_dir/bsd-gpart-list.txt
1711                         gpart show &> $debug_data_dir/bsd-gpart-show.txt
1712                         gpart status &> $debug_data_dir/bsd-gpart-status.txt
1713                         swapctl -l &> $debug_data_dir/bsd-swapctl-l.txt
1714                         swapon -s &> $debug_data_dir/swapon-s.txt
1715                         sysctl -b kern.geom.conftxt  &> $debug_data_dir/bsd-sysctl-b-kern.geom.conftxt.txt
1716                         sysctl -b kern.geom.confxml &> $debug_data_dir/bsd-sysctl-b-kern.geom.confxml.txt
1717                         zfs list &> $debug_data_dir/bsd-zfs-list.txt
1718                         zpool list &> $debug_data_dir/bsd-zpool-list.txt
1719                         zpool list -v &> $debug_data_dir/bsd-zpool-list-v.txt
1720                         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
1721                         df -P &> $debug_data_dir/bsd-df-P-no-excludes.txt
1722                         cat /proc/mdstat &> $debug_data_dir/proc-mdstat.txt
1723                         cat $FILE_PARTITIONS &> $debug_data_dir/proc-partitions.txt
1724                         cat $FILE_SCSI &> $debug_data_dir/proc-scsi.txt
1725                         cat $FILE_MOUNTS &> $debug_data_dir/proc-mounts.txt
1726                         cat /proc/sys/dev/cdrom/info &> $debug_data_dir/proc-cdrom-info.txt
1727                         ls /proc/ide/ &> $debug_data_dir/proc-ide.txt
1728                         cat /proc/ide/*/* &> $debug_data_dir/proc-ide-hdx-cat.txt
1729                         cat /etc/fstab &> $debug_data_dir/etc-fstab.txt
1730                         cat /etc/mtab &> $debug_data_dir/etc-mtab.txt
1731                 fi
1732                 echo 'Creating inxi output file now. This can take a few seconds...'
1733                 echo "Starting $SCRIPT_NAME from: $start_directory"
1734                 cd $start_directory
1735                 $SCRIPT_PATH/$SCRIPT_NAME -FRploudxxx -c 0 -@ 8 > $SCRIPT_DATA_DIR/$debug_data_dir/inxi-FRploudxxx.txt
1736                 cp $LOG_FILE $SCRIPT_DATA_DIR/$debug_data_dir
1737                 if [[ -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz ]];then
1738                         echo "Found and removing previous tar.gz data file: $debug_data_dir.tar.gz"
1739                         rm -f $SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1740                 fi
1741                 cd $SCRIPT_DATA_DIR
1742                 echo 'Creating tar.gz compressed file of this material now. Contents:'
1743                 echo $Line
1744                 tar -cvzf $debug_data_dir.tar.gz $debug_data_dir
1745                 echo $Line
1746                 echo 'Cleaning up leftovers...'
1747                 rm -rf $debug_data_dir
1748                 echo 'Testing gzip file integrity...'
1749                 gzip -t $debug_data_dir.tar.gz
1750                 if [[ $? -gt 0 ]];then
1751                         echo 'Data in gz is corrupted, removing gzip file, try running data collector again.'
1752                         rm -f $debug_data_dir.tar.gz
1753                         echo "Data in gz is corrupted, removed gzip file" >> $debug_data_dir/gzip-error.txt
1754                 else
1755                         echo 'All done, you can find your data gzipped directory here:'
1756                         completed_gz_file=$SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1757                         echo $completed_gz_file
1758                         if [[ $B_UPLOAD_DEBUG_DATA == 'true' ]];then
1759                                 echo $Line
1760                                 if [[ $b_run_xiin == 'true' ]];then
1761                                         echo "Running automatic upload of data to remote server $ftp_upload now..."
1762                                         python ./$xiin_file --version
1763                                         python ./$xiin_file -u $completed_gz_file $ftp_upload
1764                                         if [[ $? -gt 0 ]];then
1765                                                 echo $Line
1766                                                 echo "Error: looks like the ftp upload failed. Error number: $?"
1767                                                 echo "The ftp upload failed. Error number: $?" >> $debug_data_dir/xiin-error.txt
1768                                         fi
1769                                 else
1770                                         echo 'Unable to run the automoatic ftp upload because of an error with the xiin download.'
1771                                         echo "Unable to run the automoatic ftp upload because of an error with the xiin download" >> $debug_data_dir/xiin-error.txt
1772                                 fi
1773                         else
1774                                 echo 'You can upload this here using most file managers: ftp.techpatterns.com/incoming'
1775                                 echo 'then let a maintainer know it is uploaded.'
1776                         fi
1777                 fi
1778         else
1779                 echo 'This feature only available in console or shell client! Exiting now.'
1780         fi
1781         exit 0
1782 }
1783
1784 check_recommends_user_output()
1785 {
1786         local Line='-----------------------------------------------------------------------------------------'
1787         local gawk_version='N/A' sed_version='N/A' sudo_version='N/A' python_version='N/A'
1788         
1789         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1790                 print_screen_output "Sorry, you can't run this option in an IRC client."
1791                 exit 1
1792         fi
1793         
1794         initialize_paths
1795         
1796         echo "$SCRIPT_NAME will now begin checking for the programs it needs to operate. First a check of"
1797         echo "the main languages and tools $SCRIPT_NAME uses. Python is only for debugging data collection."
1798         echo $Line
1799         echo "Bash version: $( bash --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU bash/ {print $4}' )"
1800         if [[ -n $( type -p gawk ) ]];then
1801                 gawk_version=$( gawk --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU Awk/ {print $3}' )
1802         fi
1803         if [[ -n $( type -p sed ) ]];then
1804                 sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU sed version/ {print $4}' )
1805                 if [[ -z $sed_version ]];then
1806                         # note: bsd sed shows error with --version flag
1807                         sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^sed: illegal option/ {print "BSD sed"}' )
1808                 fi
1809         fi
1810         if [[ -n $( type -p sudo ) ]];then
1811                 sudo_version=$( sudo -V 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Sudo version/ {print $3}' )
1812         fi
1813         if [[ -n $( type -p python ) ]];then
1814                 python_version=$( python --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Python/ {print $2}' )
1815         fi
1816         echo "Gawk version: $gawk_version"
1817         echo "Sed version: $sed_version"
1818         echo "Sudo version: $sudo_version"
1819         echo "Python version: $python_version"
1820         echo $Line
1821         echo "Test One: Required System Directories."
1822         echo "If one of these system directories is missing, $SCRIPT_NAME cannot operate:"
1823         echo 
1824         check_recommends_items 'required-dirs'
1825         echo "Test Two: Required Core Applications."
1826         echo "If one of these applications is missing, $SCRIPT_NAME cannot operate:"
1827         echo 
1828         check_recommends_items 'required-apps'
1829         echo 'Test Three: Script Recommends for Graphics Features. If you do not use X these do not matter.'
1830         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1831         echo 
1832         check_recommends_items 'recommended-x-apps'
1833         echo 'Test Four: Script Recommends for Remaining Features.' 
1834         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1835         echo 
1836         check_recommends_items 'recommended-apps'
1837         echo 'Test Five: System Directories for Various Information.' 
1838         echo "If one of these directories is missing, $SCRIPT_NAME will have incomplete output:"
1839         echo 
1840         check_recommends_items 'system-dirs'
1841         echo 'All tests completed.' 
1842 }
1843 # args: $1 - check item
1844 check_recommends_items()
1845 {
1846         local item='' item_list='' item_string='' missing_items='' missing_string=''
1847         local package='' application='' feature='' type='' starter='' finisher=''
1848         local package_deb='' package_pacman='' package_rpm='' 
1849         local print_string='' separator=''
1850         local required_dirs='/proc /sys'
1851         # package-owner: 1 - debian/ubuntu; 2 - arch; 3 - yum/rpm
1852         # pardus: pisi sf -q /usr/bin/package
1853         local required_apps='
1854         df:coreutils~coreutils~coreutils~:partition_data 
1855         gawk:gawk~gawk~gawk~:core_tool
1856         grep:grep~grep~grep~:string_search 
1857         lspci:pciutils~pciutils~pciutils~:hardware_data 
1858         ps:procps~procps~procps~:process_data 
1859         readlink:coreutils~coreutils~coreutils~: 
1860         sed:sed~sed~sed~:string_replace 
1861         tr:coreutils~coreutils~coreutils~:character_replace 
1862         uname:uname~coreutils~coreutils~:kernel_data 
1863         uptime:procps~procps~procps~: 
1864         wc:coreutils~coreutils~coreutils~:word_character_count
1865         '
1866         local x_recommends='
1867         glxinfo:mesa-utils~mesa-demos~glx-utils_(openSUSE_12.3_and_later_Mesa-demo-x)~:-G_glx_info 
1868         xdpyinfo:X11-utils~xorg-xdpyinfo~xorg-x11-utils~:-G_multi_screen_resolution 
1869         xprop:X11-utils~xorg-xprop~x11-utils~:-S_desktop_data 
1870         xrandr:x11-xserver-utils~xrandr~x11-server-utils~:-G_single_screen_resolution
1871         '
1872         local recommended_apps='
1873         dmidecode:dmidecode~dmidecode~dmidecode~:-M_if_no_sys_machine_data 
1874         file:file~file~file~:-o_unmounted_file_system
1875         hddtemp:hddtemp~hddtemp~hddtemp~:-Dx_show_hdd_temp 
1876         ifconfig:net-tools~net-tools~net-tools~:-i_ip_lan-deprecated
1877         ip:iproute~iproute2~iproute~:-i_ip_lan
1878         sensors:lm-sensors~lm_sensors~lm-sensors~:-s_sensors_output
1879         strings:binutils~~~:-I_sysvinit_version
1880         lsusb:usbutils~usbutils~usbutils~:-A_usb_audio;-N_usb_networking 
1881         modinfo:module-init-tools~module-init-tools~module-init-tools~:-Ax,-Nx_module_version 
1882         runlevel:sysvinit~sysvinit~systemd~:-I_runlevel
1883         sudo:sudo~sudo~sudo~:-Dx_hddtemp-user;-o_file-user
1884         '
1885         local recommended_dirs='
1886         /sys/class/dmi/id:-M_system,_motherboard,_bios
1887         /dev:-l,-u,-o,-p,-P,-D_disk_partition_data
1888         /dev/disk/by-label:-l,-o,-p,-P_partition_labels
1889         /dev/disk/by-uuid:-u,-o,-p,-P_partition_uuid
1890         /var/run/dmesg.boot:-C,-f_(BSD_only)
1891         '
1892         
1893         case $1 in
1894                 required-dirs)
1895                         item_list=$required_dirs
1896                         item_string='Required file system'
1897                         missing_string='system directories'
1898                         type='directories'
1899                         ;;
1900                 required-apps)
1901                         item_list=$required_apps
1902                         item_string='Required application'
1903                         missing_string='applications, and their corresponding packages,'
1904                         type='applications'
1905                         ;;
1906                 recommended-x-apps)
1907                         item_list=$x_recommends
1908                         item_string='Recommended X application'
1909                         missing_string='applications, and their corresponding packages,'
1910                         type='applications'
1911                         ;;
1912                 recommended-apps)
1913                         item_list=$recommended_apps
1914                         item_string='Recommended application'
1915                         missing_string='applications, and their corresponding packages,'
1916                         type='applications'
1917                         ;;
1918                 system-dirs)
1919                         item_list=$recommended_dirs
1920                         item_string='System directory'
1921                         missing_string='system directories'
1922                         type='directories'
1923                         ;;
1924         esac
1925         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
1926         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
1927         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
1928         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
1929         
1930         for item in $item_list
1931         do
1932                 if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 0 ]];then
1933                         application=$item
1934                         package=''
1935                         feature=''
1936                         location=''
1937                 elif [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 1 ]];then
1938                         application=$( cut -d ':' -f 1 <<< $item )
1939                         package=''
1940                         feature=$( cut -d ':' -f 2 <<< $item )
1941                         location=''
1942                 else
1943                         application=$( cut -d ':' -f 1 <<< $item )
1944                         package=$( cut -d ':' -f 2 <<< $item )
1945                         location=$( type -p $application )
1946                         if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 2 ]];then
1947                                 feature=$( cut -d ':' -f 3 <<< $item )
1948                         else
1949                                 feature=''
1950                         fi
1951                 fi
1952                 if [[ -n $feature ]];then
1953                         print_string="$item_string: $application (info: $( sed 's/_/ /g' <<< $feature ))"
1954                 else
1955                         print_string="$item_string: $application"
1956                 fi
1957                 
1958                 starter="$( sed -e :a -e 's/^.\{1,75\}$/&./;ta' <<< $print_string )"
1959                 if [[ -z $( grep '^/' <<< $application ) && -n $location ]] || [[ -d $application ]];then
1960                         if [[ -n $location ]];then
1961                                 finisher=" $location"
1962                         else
1963                                 finisher=" Present"
1964                         fi
1965                 else
1966                         finisher=" Missing"
1967                         missing_items="$missing_items$separator$application:$package"
1968                         separator=' '
1969                 fi
1970                 
1971                 echo "$starter$finisher"
1972         done
1973         echo 
1974         if [[ -n $missing_items ]];then
1975                 echo "The following $type are missing from your system:"
1976                 for item in $missing_items
1977                 do
1978                         application=$( cut -d ':' -f 1 <<< $item )
1979                         if [[ $type == 'applications' ]];then
1980                                 # echo '--------------------------------------------------------'
1981                                 echo
1982                                 package=$( cut -d ':' -f 2 <<< $item )
1983                                 package_deb=$( cut -d '~' -f 1 <<< $package )
1984                                 package_pacman=$( cut -d '~' -f 2 <<< $package )
1985                                 package_rpm=$( cut -d '~' -f 3 <<< $package )
1986                                 echo "Application: $application"
1987                                 echo "To add to your system, install the proper distribution package for your system:"
1988                                 echo "Debian/Ubuntu: $package_deb :: Arch Linux: $package_pacman :: Redhat/Fedora/Suse: $package_rpm"
1989                         else
1990                                 echo "Directory: $application"
1991                         fi
1992                 done
1993                 if [[ $item_string == 'System directory' ]];then
1994                         echo "These directories are created by the kernel, so don't worry if they are not present."
1995                 fi
1996         else
1997                 echo "All the $( cut -d ' ' -f 1 <<< $item_string | sed -e 's/Re/re/' -e 's/Sy/sy/' ) $type are present."
1998         fi
1999         echo $Line
2000 }
2001
2002 #### -------------------------------------------------------------------
2003 #### print / output cleaners
2004 #### -------------------------------------------------------------------
2005
2006 # inxi speaks through here. When run by Konversation script alias mode, uses DCOP
2007 # for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e
2008 # note: dcop does not seem able to handle \n so that's being stripped out and replaced with space.
2009 print_screen_output()
2010 {
2011         eval $LOGFS
2012         # the double quotes are needed to avoid losing whitespace in data when certain output types are used
2013         local print_data="$( echo -e "$1" )"
2014
2015         # just using basic debugger stuff so you can tell which thing is printing out the data. This
2016         # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off
2017         # the redundant debugger output which as far as I can tell does exactly nothing to help debugging.
2018         if [[ $DEBUG -gt 5 ]];then
2019                 if [[ $KONVI -eq 1 ]];then
2020                         # konvi doesn't seem to like \n characters, it just prints them literally
2021                         # print_data="$( tr '\n' ' ' <<< "$print_data" )"
2022                         # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'"
2023                         print_data="KP-$KONVI: $print_data"
2024                 elif [[ $KONVI -eq 2 ]];then
2025                         # echo "konvi='$KONVI' saying : '$print_data'"
2026                         print_data="KP-$KONVI: $print_data"
2027                 else
2028                         # echo "printing out: '$print_data'"
2029                         print_data="P: $print_data"
2030                 fi
2031         fi
2032
2033         if [[ $KONVI -eq 1 && $B_DCOP == 'true' ]]; then ## dcop Konversation (<= 1.1 (qt3))
2034                 # konvi doesn't seem to like \n characters, it just prints them literally
2035                 $print_data="$( tr '\n' ' ' <<< "$print_data" )"
2036                 dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data"
2037
2038         elif [[ $KONVI -eq 3 && $B_QDBUS == 'true' ]]; then ## dbus Konversation (> 1.2 (qt4))
2039                 qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data"
2040
2041 #       elif [[ $IRC_CLIENT == 'X-Chat' ]]; then
2042 #               qdbus org.xchat.service print "$print_data\n"
2043
2044         else
2045                 # the -n is needed to avoid double spacing of output in terminal
2046                 echo -ne "$print_data\n"
2047         fi
2048         eval $LOGFE
2049 }
2050
2051 ## this handles all verbose line construction with indentation/line starter
2052 ## args: $1 - null (, actually: " ") or line starter; $2 - line content
2053 create_print_line()
2054 {
2055         eval $LOGFS
2056         printf "${C1}%-${INDENT}s${C2} %s" "$1" "$2"
2057         eval $LOGFE
2058 }
2059
2060 # this removes newline and pipes.
2061 # args: $1 - string to clean
2062 remove_erroneous_chars()
2063 {
2064         eval $LOGFS
2065         ## RS is input record separator
2066         ## gsub is substitute;
2067         gawk '
2068         BEGIN {
2069                 RS=""
2070         }
2071         {
2072                 gsub(/\n$/,"")         ## (newline; end of string) with (nothing)
2073                 gsub(/\n/," ");        ## (newline) with (space)
2074                 gsub(/^ *| *$/, "")    ## (pipe char) with (nothing)
2075                 gsub(/  +/, " ")       ## ( +) with (space)
2076                 gsub(/ [ ]+/, " ")     ## ([ ]+) with (space)
2077                 gsub(/^ +| +$/, "")    ## (pipe char) with (nothing)
2078                 printf $0
2079         }' "$1"      ## prints (returns) cleaned input
2080         eval $LOGFE
2081 }
2082
2083 #### -------------------------------------------------------------------
2084 #### parameter handling, print usage functions.
2085 #### -------------------------------------------------------------------
2086
2087 # Get the parameters. Note: standard options should be lower case, advanced or testing, upper
2088 # args: $1 - full script startup args: $@
2089 get_parameters()
2090 {
2091         eval $LOGFS
2092         local opt='' wget_test='' debug_data_type='' weather_flag='wW:' 
2093         local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false
2094
2095         # if distro maintainers don't want the weather feature disable it
2096         if [[ $B_ALLOW_WEATHER == 'false' ]];then
2097                 weather_flag=''
2098                 
2099         fi
2100         if [[ $1 == '--version' ]];then
2101                 print_version_info
2102                 exit 0
2103         elif [[ $1 == '--help' ]];then
2104                 show_options
2105                 exit 0
2106         elif [[ $1 == '--recommends' ]];then
2107                 check_recommends_user_output
2108                 exit 0
2109         # the short form only runs if no args output args are used
2110         # no need to run through these if there are no args
2111         # reserved for future use: -g for extra Graphics; -m for extra Machine; -d for extra Disk
2112         elif [[ -n $1 ]];then
2113                 while getopts Abc:CdDfFGhHiIlMnNopPrRsSt:uUv:V${weather_flag}xzZ%@:!: opt
2114                 do
2115                         case $opt in
2116                         A)      B_SHOW_AUDIO='true'
2117                                 use_short='false'
2118                                 ;;
2119                         b)      use_short='false'
2120                                 B_SHOW_BASIC_CPU='true'
2121                                 B_SHOW_BASIC_RAID='true'
2122                                 B_SHOW_DISK_TOTAL='true'
2123                                 B_SHOW_GRAPHICS='true'
2124                                 B_SHOW_INFO='true'
2125                                 B_SHOW_MACHINE='true'
2126                                 B_SHOW_NETWORK='true'
2127                                 B_SHOW_SYSTEM='true'
2128                                 ;;
2129                         c)      if [[ -n $( grep -E '^[0-9][0-9]?$' <<< $OPTARG ) ]];then
2130                                         case $OPTARG in
2131                                                 99)
2132                                                         B_RUN_COLOR_SELECTOR='true'
2133                                                         COLOR_SELECTION='global'
2134                                                         ;;
2135                                                 98)
2136                                                         B_RUN_COLOR_SELECTOR='true'
2137                                                         COLOR_SELECTION='irc-console'
2138                                                         ;;
2139                                                 97)
2140                                                         B_RUN_COLOR_SELECTOR='true'
2141                                                         COLOR_SELECTION='irc-virtual-terminal'
2142                                                         ;;
2143                                                 96)
2144                                                         B_RUN_COLOR_SELECTOR='true'
2145                                                         COLOR_SELECTION='irc'
2146                                                         ;;
2147                                                 95)
2148                                                         B_RUN_COLOR_SELECTOR='true'
2149                                                         COLOR_SELECTION='virtual-terminal'
2150                                                         ;;
2151                                                 94)
2152                                                         B_RUN_COLOR_SELECTOR='true'
2153                                                         COLOR_SELECTION='console'
2154                                                         ;;
2155                                                 *)      
2156                                                         B_COLOR_SCHEME_SET='true'
2157                                                         ## note: not sure about this, you'd think user values should be overridden, but
2158                                                         ## we'll leave this for now
2159                                                         if [[ -z $COLOR_SCHEME ]];then
2160                                                                 set_color_scheme "$OPTARG"
2161                                                         fi
2162                                                         ;;
2163                                         esac
2164                                 else
2165                                         error_handler 3 "$OPTARG"
2166                                 fi
2167                                 ;;
2168                         C)      B_SHOW_CPU='true'
2169                                 use_short='false'
2170                                 ;;
2171                         d)      B_SHOW_DISK='true'
2172                                 B_SHOW_FULL_OPTICAL='true'
2173                                 use_short='false'
2174                                 # error_handler 20 "-d has been replaced by -b"
2175                                 ;;
2176                         D)      B_SHOW_DISK='true'
2177                                 use_short='false'
2178                                 ;;
2179                         f)      B_SHOW_CPU='true'
2180                                 B_CPU_FLAGS_FULL='true'
2181                                 use_short='false'
2182                                 ;;
2183                         F)      # B_EXTRA_DATA='true'
2184                                 B_SHOW_ADVANCED_NETWORK='true'
2185                                 B_SHOW_AUDIO='true'
2186                                 # B_SHOW_BASIC_OPTICAL='true'
2187                                 B_SHOW_CPU='true'
2188                                 B_SHOW_DISK='true'
2189                                 B_SHOW_GRAPHICS='true'
2190                                 B_SHOW_INFO='true'
2191                                 B_SHOW_MACHINE='true'
2192                                 B_SHOW_NETWORK='true'
2193                                 B_SHOW_PARTITIONS='true'
2194                                 B_SHOW_RAID='true'
2195                                 B_SHOW_SENSORS='true'
2196                                 B_SHOW_SYSTEM='true'
2197                                 use_short='false'
2198                                 ;;
2199                         G)      B_SHOW_GRAPHICS='true'
2200                                 use_short='false'
2201                                 ;;
2202                         i)      B_SHOW_IP='true'
2203                                 B_SHOW_NETWORK='true'
2204                                 B_SHOW_ADVANCED_NETWORK='true'
2205                                 use_short='false'
2206                                 ;;
2207                         I)      B_SHOW_INFO='true'
2208                                 use_short='false'
2209                                 ;;
2210                         l)      B_SHOW_LABELS='true'
2211                                 B_SHOW_PARTITIONS='true'
2212                                 use_short='false'
2213                                 ;;
2214                         M)      B_SHOW_MACHINE='true'
2215                                 use_short='false'
2216                                 ;;
2217                         n)      B_SHOW_ADVANCED_NETWORK='true'
2218                                 B_SHOW_NETWORK='true'
2219                                 use_short='false'
2220                                 ;;
2221                         N)      B_SHOW_NETWORK='true'
2222                                 use_short='false'
2223                                 ;;
2224                         o)      B_SHOW_UNMOUNTED_PARTITIONS='true'
2225                                 use_short='false'
2226                                 ;;
2227                         p)      B_SHOW_PARTITIONS_FULL='true'
2228                                 B_SHOW_PARTITIONS='true'
2229                                 use_short='false'
2230                                 ;;
2231                         P)      B_SHOW_PARTITIONS='true'
2232                                 use_short='false'
2233                                 ;;
2234                         r)      B_SHOW_REPOS='true'
2235                                 use_short='false'
2236                                 ;;
2237                         R)      B_SHOW_RAID='true'
2238                                 # it turns out only users with mdraid software installed will have raid,
2239                                 # so unless -R is explicitly called, blank -b/-F/-v6 and less output will not show
2240                                 # error if file is missing.
2241                                 B_SHOW_RAID_R='true'
2242                                 use_short='false'
2243                                 ;;
2244                         s)      B_SHOW_SENSORS='true'
2245                                 use_short='false'
2246                                 ;;
2247                         S)      B_SHOW_SYSTEM='true'
2248                                 use_short='false'
2249                                 ;;
2250                         t)      if [[ -n $( grep -E '^(c|m|cm|mc)([1-9]|1[0-9]|20)?$' <<< $OPTARG ) ]];then
2251                                         use_short='false'
2252                                         if [[ -n $( grep -E '[0-9]+' <<< $OPTARG ) ]];then
2253                                                 PS_COUNT=$( sed 's/[^0-9]//g' <<< $OPTARG )
2254                                         fi
2255                                         if [[ -n $( grep 'c' <<< $OPTARG ) ]];then
2256                                                 B_SHOW_PS_CPU_DATA='true'
2257                                         fi
2258                                         if [[ -n $( grep 'm' <<< $OPTARG ) ]];then
2259                                                 B_SHOW_PS_MEM_DATA='true'
2260                                         fi
2261                                 else
2262                                         error_handler 13 "$OPTARG"
2263                                 fi
2264                                 ;;
2265                         u)      B_SHOW_UUIDS='true'
2266                                 B_SHOW_PARTITIONS='true'
2267                                 use_short='false'
2268                                 ;;
2269                         v)      if [[ -n $( grep -E "^[0-9][0-9]?$" <<< $OPTARG ) && $OPTARG -le $VERBOSITY_LEVELS ]];then
2270                                         if [[ $OPTARG -ge 1 ]];then
2271                                                 use_short='false'
2272                                                 B_SHOW_BASIC_CPU='true'
2273                                                 B_SHOW_DISK_TOTAL='true'
2274                                                 B_SHOW_GRAPHICS='true'
2275                                                 B_SHOW_INFO='true'
2276                                                 B_SHOW_SYSTEM='true'
2277                                         fi
2278                                         if [[ $OPTARG -ge 2 ]];then
2279                                                 B_SHOW_BASIC_DISK='true'
2280                                                 B_SHOW_BASIC_RAID='true'
2281                                                 B_SHOW_MACHINE='true'
2282                                                 B_SHOW_NETWORK='true'
2283                                         fi
2284                                         if [[ $OPTARG -ge 3 ]];then
2285                                                 B_SHOW_ADVANCED_NETWORK='true'
2286                                                 B_SHOW_CPU='true'
2287                                                 B_EXTRA_DATA='true'
2288                                         fi
2289                                         if [[ $OPTARG -ge 4 ]];then
2290                                                 B_SHOW_DISK='true'
2291                                                 B_SHOW_PARTITIONS='true'
2292                                         fi
2293                                         if [[ $OPTARG -ge 5 ]];then
2294                                                 B_SHOW_AUDIO='true'
2295                                                 B_SHOW_BASIC_OPTICAL='true'
2296                                                 B_SHOW_SENSORS='true'
2297                                                 B_SHOW_LABELS='true'
2298                                                 B_SHOW_UUIDS='true'
2299                                                 B_SHOW_RAID='true'
2300                                         fi
2301                                         if [[ $OPTARG -ge 6 ]];then
2302                                                 B_SHOW_FULL_OPTICAL='true'
2303                                                 B_SHOW_PARTITIONS_FULL='true'
2304                                                 B_SHOW_UNMOUNTED_PARTITIONS='true'
2305                                                 B_EXTRA_EXTRA_DATA='true'
2306                                         fi
2307                                         if [[ $OPTARG -ge 7 ]];then
2308                                                 B_EXTRA_EXTRA_EXTRA_DATA='true'
2309                                                 B_SHOW_IP='true'
2310                                                 B_SHOW_RAID_R='true'
2311                                         fi
2312                                 else
2313                                         error_handler 4 "$OPTARG"
2314                                 fi
2315                                 ;;
2316                         U)      if [[ $B_ALLOW_UPDATE == 'true' ]];then
2317                                         script_self_updater "$SCRIPT_DOWNLOAD" 'svn server' "$opt"
2318                                 else
2319                                         error_handler 17 "-$opt"
2320                                 fi
2321                                 ;;
2322                         V)      print_version_info
2323                                 exit 0
2324                                 ;;
2325                         w)      B_SHOW_WEATHER=true
2326                                 use_short='false'
2327                                 ;;
2328                         W)      ALTERNATE_WEATHER_LOCATION=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'  <<< $OPTARG )
2329                                 if [[ -n $( grep -Esi '([^,]+,.+|[0-9-]+)' <<< $ALTERNATE_WEATHER_LOCATION ) ]];then
2330                                         B_SHOW_WEATHER=true
2331                                         use_short='false'
2332                                 else
2333                                         error_handler 18 "-$opt: '$OPTARG'" "city,state OR latitude,longitude OR postal/zip code."
2334                                 fi
2335                                 ;;
2336                         # this will trigger either with x, xx, xxx or with Fx but not with xF
2337                         x)      if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2338                                         B_EXTRA_EXTRA_EXTRA_DATA='true'
2339                                 elif [[ $B_EXTRA_DATA == 'true' ]];then
2340                                         B_EXTRA_EXTRA_DATA='true'
2341                                 else
2342                                         B_EXTRA_DATA='true'
2343                                 fi
2344                                 ;;
2345                         z)      B_OUTPUT_FILTER='true'
2346                                 ;;
2347                         Z)      B_OVERRIDE_FILTER='true'
2348                                 ;;
2349                         h)      show_options
2350                                 exit 0
2351                                 ;;
2352                         H)      show_options 'full'
2353                                 exit 0
2354                                 ;;
2355                         ## debuggers and testing tools
2356                         %)      B_HANDLE_CORRUPT_DATA='true'
2357                                 ;;
2358                         @)      if [[ -n $( grep -E "^([1-9]|1[0-4])$" <<< $OPTARG ) ]];then
2359                                         DEBUG=$OPTARG
2360                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2361                                                 B_UPLOAD_DEBUG_DATA='true'
2362                                         fi
2363                                         exec 2>&1
2364                                         # switch on logging only for -@ 8-10
2365                                         case $OPTARG in
2366                                                 8|9|10)
2367                                                         if [[ $OPTARG -eq 10 ]];then
2368                                                                 B_LOG_COLORS='true'
2369                                                         elif [[ $OPTARG -eq 9 ]];then           
2370                                                                 B_LOG_FULL_DATA='true'
2371                                                         fi
2372                                                         B_USE_LOGGING='true'
2373                                                         # pack the logging data for evals function start/end
2374                                                         LOGFS=$LOGFS_STRING
2375                                                         LOGFE=$LOGFE_STRING
2376                                                         create_rotate_logfiles # create/rotate logfiles before we do anything else
2377                                                         ;;
2378                                                 11|12|13|14)
2379                                                         case $OPTARG in
2380                                                                 11)
2381                                                                         debug_data_type='sys'
2382                                                                         ;;
2383                                                                 12)
2384                                                                         debug_data_type='xorg'
2385                                                                         ;;
2386                                                                 13)
2387                                                                         debug_data_type='disk'
2388                                                                         ;;
2389                                                                 14)
2390                                                                         debug_data_type='all'
2391                                                                         ;;
2392                                                         esac
2393                                                         initialize_data
2394                                                         debug_data_collector $debug_data_type
2395                                                         ;;
2396                                         esac
2397                                 else
2398                                         error_handler 9 "$OPTARG"
2399                                 fi
2400                                 ;;
2401                         !)      # test for various supported methods
2402                                 case $OPTARG in
2403                                         1)      B_TESTING_1='true'
2404                                                 ;;
2405                                         2)      B_TESTING_2='true'
2406                                                 ;;
2407                                         3)      B_TESTING_1='true'
2408                                                 B_TESTING_2='true'
2409                                                 ;;
2410                                         1[0-6]|http*)
2411                                                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
2412                                                         case $OPTARG in
2413                                                                 10)
2414                                                                         script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server' "$opt $OPTARG"
2415                                                                         ;;
2416                                                                 11)
2417                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server' "$opt $OPTARG"
2418                                                                         ;;
2419                                                                 12)
2420                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server' "$opt $OPTARG"
2421                                                                         ;;
2422                                                                 13)
2423                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server' "$opt $OPTARG"
2424                                                                         ;;
2425                                                                 14)
2426                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server' "$opt $OPTARG"
2427                                                                         ;;
2428                                                                 15)
2429                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_BSD" 'svn: branch bsd server' "$opt $OPTARG"
2430                                                                         ;;
2431                                                                 16)
2432                                                                         script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_GNUBSD" 'svn: branch gnubsd server' "$opt $OPTARG"
2433                                                                         ;;
2434                                                                 http*)
2435                                                                         script_self_updater "$OPTARG" 'alt server' "$opt <http...>"
2436                                                                         ;;
2437                                                         esac
2438                                                 else
2439                                                         error_handler 17 "-$opt $OPTARG"
2440                                                 fi
2441                                                 ;;
2442                                         30)
2443                                                 B_RUNNING_IN_SHELL='true'
2444                                                 ;;
2445                                         31)
2446                                                 B_SHOW_HOST='false'
2447                                                 ;;
2448                                         32)
2449                                                 B_SHOW_HOST='true'
2450                                                 ;;
2451                                         ftp*)
2452                                                 ALTERNATE_FTP="$OPTARG"
2453                                                 ;;
2454                                         # for weather function, allows user to set an alternate weather location
2455                                         location=*)
2456                                                 error_handler 19 "-$opt location=" "-W"
2457                                                 ;;
2458                                         *)      error_handler 11 "$OPTARG"
2459                                                 ;;
2460                                 esac
2461                                 ;;
2462                         *)      error_handler 7 "$1"
2463                                 ;;
2464                         esac
2465                 done
2466         fi
2467         ## this must occur here so you can use the debugging flag to show errors
2468         ## Reroute all error messages to the bitbucket (if not debugging)
2469         if [[ $DEBUG -eq 0 ]];then
2470                 exec 2>/dev/null
2471         fi
2472         #((DEBUG)) && exec 2>&1 # This is for debugging konversation
2473
2474         # after all the args have been processed, if no long output args used, run short output
2475         if [[ $use_short == 'true' ]];then
2476                 B_SHOW_SHORT_OUTPUT='true'
2477         fi
2478         # just in case someone insists on using -zZ
2479         if [[ $B_OVERRIDE_FILTER == 'true' ]];then
2480                 B_OUTPUT_FILTER='false'
2481         fi
2482         # change basic to full if user requested it or if arg overrides it
2483         if [[ $B_SHOW_RAID == 'true' && $B_SHOW_BASIC_RAID == 'true' ]];then
2484                 B_SHOW_BASIC_RAID='false'
2485         fi
2486         
2487         
2488         eval $LOGFE
2489 }
2490
2491 ## print out help menu, not including Testing or Debugger stuff because it's not needed
2492 show_options()
2493 {
2494         local color_scheme_count=$(( ${#A_COLOR_SCHEMES[@]} - 1 ))
2495         local partition_string='partition' partition_string_u='Partition'
2496         
2497         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
2498                 print_screen_output "Sorry, you can't run the help option in an IRC client."
2499                 exit 1
2500         fi
2501         if [[ -n $BSD_TYPE ]];then
2502                 partition_string='slice'
2503                 partition_string_u='Slice'
2504         fi
2505         # print_lines_basic "0" "" ""
2506         # print_lines_basic "1" "" ""
2507         # print_lines_basic "2" "" ""
2508         # print_screen_output " "
2509         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."
2510         print_screen_output " "
2511         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."
2512         
2513         print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
2514         print_screen_output "Output Control Options:"
2515         print_lines_basic "1" "-A" "Audio/sound card information."
2516         print_lines_basic "1" "-b" "Basic output, short form. Like $SCRIPT_NAME^-v^2, only minus hard disk names."
2517         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."
2518         print_lines_basic "1" "" "Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME^-c^11"
2519         print_lines_basic "1" "" "Color selectors for each type display (NOTE: irc and global only show safe color set):"
2520 #       print_screen_output "    Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11"
2521 #       print_screen_output "    Color selectors for each type display (NOTE: irc and global only show safe color set):"
2522         print_lines_basic "2" "94" "Console, out of X"
2523         print_lines_basic "2" "95" "Terminal, running in X - like xTerm"
2524         print_lines_basic "2" "96" "Gui IRC, running in X - like Xchat, Quassel, Konversation etc."
2525         print_lines_basic "2" "97" "Console IRC running in X - like irssi in xTerm"
2526         print_lines_basic "2" "98" "Console IRC not in  X"
2527         print_lines_basic "2" "99" "Global - Overrides/removes all settings. Setting specific removes global."
2528         print_lines_basic "1" "-C" "CPU output, including per CPU clockspeed (if available)."
2529         print_lines_basic "1" "-d" "Optical drive data. Same as -Dd. See also -x and -xx."
2530         print_lines_basic "1" "-D" "Full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB. See also -x and -xx."
2531         print_lines_basic "1" "-f" "All cpu flags, triggers -C. Not shown with -F to avoid spamming. ARM cpus show 'features'."
2532         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"
2533         print_lines_basic "1" "-G" "Graphic card information (card, display server type/version, resolution, glx renderer, version)."
2534         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."
2535         print_lines_basic "1" "-I" "Information: processes, uptime, memory, irc client (or shell type), $SCRIPT_NAME version."
2536         print_lines_basic "1" "-l" "${partition_string_u} labels. Default: short ${partition_string} -P. For full -p output, use: -pl (or -plu)."
2537         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."
2538         print_lines_basic "1" "-n" "Advanced Network card information. Same as -Nn. Shows interface, speed, mac id, state, etc."
2539         print_lines_basic "1" "-N" "Network card information. With -x, shows PCI BusID, Port number."
2540         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^"
2541         print_lines_basic "1" "-p" "Full ${partition_string} information (-P plus all other detected ${partition_string}s)."
2542         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."
2543         print_lines_basic "1" "-r" "Distro repository data. Supported repo types: APT; PACMAN; PISI; YUM; URPMQ; Ports."
2544         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."
2545         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."
2546         print_lines_basic "1" "-S" "System information: host name, kernel, desktop environment (if in X), distro"
2547         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"
2548         print_lines_basic "1" "" "Make sure to have no space between letters and numbers (-t^cm10 - right, -t^cm^10 - wrong)."
2549         print_lines_basic "1" "-u" "${partition_string_u} UUIDs. Default: short ${partition_string} -P. For full -p output, use: -pu (or -plu)."
2550         print_lines_basic "1" "-v" "Script verbosity levels. Verbosity level number is required. Should not be used with -b or -F"
2551         print_lines_basic "1" "" "Supported levels: 0-${VERBOSITY_LEVELS} Example: $SCRIPT_NAME^-v^4"
2552         print_lines_basic "2" "0" "Short output, same as: $SCRIPT_NAME"
2553         print_lines_basic "2" "1" "Basic verbose, -S + basic CPU + -G + basic Disk + -I."
2554         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"
2555         print_lines_basic "2" "3" "Advanced CPU (-C), network (-n) data, and switches on -x advanced data option."
2556         print_lines_basic "2" "4" "${partition_string_u} size/filled data (-P) for (if present):/, /home, /var/, /boot. Shows full disk data (-D)."
2557         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)."
2558         print_lines_basic "2" "6" "Full ${partition_string} (-p), unmounted ${partition_string} (-o), optical drive (-d), full raid; triggers -xx."
2559         print_lines_basic "2" "7" "Network IP data (-i); triggers -xxx."
2560         
2561         # if distro maintainers don't want the weather feature disable it
2562         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2563                 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."
2564                 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"
2565         fi
2566         print_lines_basic "1" "-x" "Adds the following extra data (only works with verbose or line output, not short form):"
2567         print_lines_basic "2" "-C" "CPU Flags, Bogomips on Cpu;"
2568         print_lines_basic "2" "-d" "Extra optical drive data; adds rev version to optical drive."
2569         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"
2570         print_lines_basic "2" "-G" "Direct rendering status for Graphics (in X)."
2571         print_lines_basic "2" "-G" "(for single gpu, nvidia driver) screen number gpu is running on."
2572         print_lines_basic "2" "-i" "IPv6 as well for LAN interface (IF) devices."
2573         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)."
2574         print_lines_basic "2" "-N -A" "Version/port(s)/driver version (if available) for Network/Audio;"
2575         print_lines_basic "2" "-N -A -G" "Network, audio, graphics, shows PCI Bus ID/Usb ID number of card."
2576         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"
2577         print_lines_basic "2" "-S" "Desktop toolkit if avaliable (GNOME/XFCE/KDE only); Kernel gcc version"
2578         print_lines_basic "2" "-t" "Memory use output to cpu (-xt c), and cpu use to memory (-xt m)."
2579         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2580                 print_lines_basic "2" "-w -W" "Wind speed and time zone (-w only)."
2581         fi
2582         print_lines_basic "1" "-xx" "Show extra, extra data (only works with verbose or line output, not short form):"
2583         print_lines_basic "2" "-A" "Chip vendor:product ID for each audio device."
2584         print_lines_basic "2" "-D" "Disk serial number."
2585         print_lines_basic "2" "-G" "Chip vendor:product ID for each video card."
2586         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."
2587         print_lines_basic "2" "-M" "Chassis information, bios rom size (dmidecode only), if data for either is available."
2588         print_lines_basic "2" "-N" "Chip vendor:product ID for each nic."
2589         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."
2590         print_lines_basic "2" "-S" "Display manager (dm) in desktop output, if in X (like kdm, gdm3, lightdm)."
2591         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2592                 print_lines_basic "2" "-w -W" "Humidity, barometric pressure."
2593         fi
2594         print_lines_basic "2" "-@ 11-14" "Automatically uploads debugger data tar.gz file to ftp.techpatterns.com. EG: $SCRIPT_NAME^-xx@14"
2595         print_lines_basic "1" "-xxx" "Show extra, extra, extra data (only works with verbose or line output, not short form):"
2596         print_lines_basic "2" "-S" "Panel/shell information in desktop output, if in X (like gnome-shell, cinnamon, mate-panel)."
2597         if [[ $B_ALLOW_WEATHER == 'true' ]];then
2598                 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)."
2599         fi
2600         print_lines_basic "1" "-z" "Security filters for IP/Mac addresses, location, user home directory name. Default on for irc clients."
2601         print_lines_basic "1" "-Z" "Absolute override for output filters. Useful for debugging networking issues in irc for example."
2602         print_screen_output " "
2603         print_screen_output "Additional Options:"
2604         print_lines_basic "4" "-h --help" "This help menu."
2605         print_lines_basic "4" "-H" "This help menu, plus developer options. Do not use dev options in normal operation!"
2606         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. "
2607         if [[ $B_ALLOW_UPDATE == 'true' ]];then
2608                 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."
2609         fi
2610         print_lines_basic "4" "-V --version" "$SCRIPT_NAME version information. Prints information then exits."
2611         print_screen_output " "
2612         print_screen_output "Debugging Options:"
2613         print_lines_basic "1" "-%" "Overrides defective or corrupted data."
2614         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."
2615         print_lines_basic "2" "1-7" "On screen debugger output"
2616         print_lines_basic "2" "8" "Basic logging"
2617         print_lines_basic "2" "9" "Full file/sys info logging"
2618         print_lines_basic "2" "10" "Color logging."
2619         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>"
2620         print_lines_basic "1" "" "For alternate ftp upload locations: Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
2621         print_lines_basic "2" "11" "With data file of xiin read of /sys."
2622         print_lines_basic "2" "12" "With xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc."
2623         print_lines_basic "2" "13" "With data from dev, disks, ${partition_string}s, etc., plus xiin data file."
2624         print_lines_basic "2" "14" "Everything, full data collection."
2625         print_screen_output " "
2626         print_screen_output "Advanced Options:"
2627         print_lines_basic "1" "-! 31" "Turns off hostname in output. Useful if showing output from servers etc."
2628         print_lines_basic "1" "-! 32" "Turns on hostname in output. Overrides global B_SHOW_HOST='false'"
2629         
2630         if [[ $1 == 'full' ]];then
2631                 print_screen_output " "
2632                 print_screen_output "Developer and Testing Options (Advanced):"
2633                 print_lines_basic "1" "-! 1" "Sets testing flag B_TESTING_1='true' to trigger testing condition 1."
2634                 print_lines_basic "1" "-! 2" "Sets testing flag B_TESTING_2='true' to trigger testing condition 2."
2635                 print_lines_basic "1" "-! 3" "Sets flags B_TESTING_1='true' and B_TESTING_2='true'."
2636                 if [[ $B_ALLOW_UPDATE == 'true' ]];then
2637                         print_lines_basic "1" "-! 10" "Triggers an update from the primary dev download server instead of svn."
2638                         print_lines_basic "1" "-! 11" "Triggers an update from svn branch one - if present, of course."
2639                         print_lines_basic "1" "-! 12" "Triggers an update from svn branch two - if present, of course."
2640                         print_lines_basic "1" "-! 13" "Triggers an update from svn branch three - if present, of course."
2641                         print_lines_basic "1" "-! 14" "Triggers an update from svn branch four - if present, of course."
2642                         print_lines_basic "1" "-! 15" "Triggers an update from svn branch BSD - if present, of course."
2643                         print_lines_basic "1" "-! 16" "Triggers an update from svn branch GNUBSD - if present, of course."
2644                         print_lines_basic "1" "-! <http://......>" "Triggers an update from whatever server you list."
2645                 fi
2646                 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. "
2647                 print_lines_basic "1" "" "Example: inxi^-!^ftp.yourserver.com/incoming^-xx@^14"
2648         fi
2649         print_screen_output " "
2650 }
2651
2652 # uses $TERM_COLUMNS to set width using $COLS_MAX as max width
2653 # IMPORTANT: minimize use of subshells here or the output is too slow
2654 # args: $1 - 0 1 2 3 4 for indentation level; $2 -line starter, like -m; $3 - content of block.
2655 print_lines_basic()
2656 {
2657         local line_width=$COLS_MAX
2658         local print_string='' indent_inner='' indent_full='' indent_x='' 
2659         local indent_working='' indent_working_full=''
2660         local line_starter='' line_1_starter='' line_x_starter='' 
2661         # note: to create a padded string below
2662         local fake_string=' ' temp_count='' line_count='' spacer=''
2663         local indent_main=6 indent_x='' b_indent_x='true' 
2664         
2665         case $1 in
2666                 # for no options, start at left edge
2667                 0)      indent_full=0
2668                         line_1_starter=''
2669                         line_x_starter=''
2670                         b_indent_x='false'
2671                         ;;
2672                 1)      indent_full=$indent_main
2673                         temp_count=${#2}
2674                         if [[ $temp_count -le $indent_full ]];then
2675                                 indent_working=$indent_full
2676                         else
2677                                 indent_working=$temp_count #$(( $temp_count + 1 ))
2678                         fi
2679                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2680                         ;;
2681                 # first left pad 2 and 3, then right pad them
2682                 2)      indent_full=$(( $indent_main + 6 ))
2683                         indent_inner=3
2684                         temp_count=${#2}
2685                         if [[ $temp_count -le $indent_inner ]];then
2686                                 indent_working=$indent_inner
2687                                 #indent_working_full=$indent_full
2688                         else
2689                                 indent_working=$(( $temp_count + 1 ))
2690                                 #indent_working_full=$(( $indent_full - $indent_inner - 1 ))
2691                         fi
2692                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2693                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
2694                         ;;
2695                 3)      indent_full=$(( $indent_main + 8 ))
2696                         indent_inner=3
2697                         temp_count=${#2}
2698                         if [[ $temp_count -le $indent_inner ]];then
2699                                 indent_working=$indent_inner
2700                         else
2701                                 indent_working=$(( $temp_count + 1 ))
2702                         fi
2703                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2704                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_full\}$/ &/;ta" <<< "$line_1_starter" )"
2705                         ;;
2706                 # for long options
2707                 4)      indent_full=$(( $indent_main + 8 ))
2708                         temp_count=${#2}
2709                         if [[ $temp_count -lt $indent_full ]];then
2710                                 indent_working=$indent_full
2711                         else
2712                                 indent_working=$temp_count #$(( $temp_count + 1 ))
2713                         fi
2714                         line_1_starter="$( sed -e :a -e "s/^.\{1,$indent_working\}$/& /;ta" <<< $2 )"
2715                         ;;
2716         esac
2717         
2718         if [[ $b_indent_x == 'true' ]];then
2719                 indent_x=$(( $indent_full + 1 ))
2720                 line_x_starter="$(printf "%${indent_x}s" '')"
2721         fi
2722         
2723         line_count=$(( $line_width - $indent_full ))
2724         
2725         # bash loop is slow, only run this if required
2726         if [[ ${#3} -gt $line_count ]];then
2727                 for word in $3
2728                 do
2729                         temp_string="$print_string$spacer$word"
2730                         spacer=' '
2731                         if [[ ${#temp_string} -lt $line_count ]];then
2732                                 print_string=$temp_string # lose any white space start/end
2733                                 # echo -n $(( $line_width - $indent_full ))
2734                         else
2735                                 if [[ -n $line_1_starter ]];then
2736                                         line_starter="$line_1_starter"
2737                                         line_1_starter=''
2738                                 else
2739                                         line_starter="$line_x_starter"
2740                                 fi
2741                                 # clean up forced connections, ie, stuff we don't want wrapping
2742                                 print_string=${print_string//\^/ }
2743                                 print_screen_output "$line_starter$print_string"
2744                                 print_string="$word$spacer" # needed to handle second word on new line
2745                                 temp_string=''
2746                                 spacer=''
2747                         fi
2748                 done
2749         else
2750                 # echo no loop
2751                 print_string=$3
2752         fi
2753         # print anything left over
2754         if [[ -n $print_string ]];then
2755                 if [[ -n $line_1_starter ]];then
2756                         line_starter="$line_1_starter"
2757                         line_1_starter=''
2758                 else
2759                         line_starter="$line_x_starter"
2760                 fi
2761                 print_string=${print_string//\^/ }
2762                 print_screen_output "$line_starter$print_string"
2763         fi
2764 }
2765 # 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'
2766 # 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'
2767 # print_lines_basic '2' '12' 'and its sss substring'
2768 # 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'
2769 # exit
2770
2771 ## print out version information for -V/--version
2772 print_version_info()
2773 {
2774         # if not in PATH could be either . or directory name, no slash starting
2775         local script_path=$SCRIPT_PATH script_symbolic_start=''
2776         if [[ $script_path == '.' ]];then
2777                 script_path=$( pwd )
2778         elif [[ -z $( grep '^/' <<< "$script_path" ) ]];then
2779                 script_path="$( pwd )/$script_path"
2780         fi
2781         # handle if it's a symbolic link, rare, but can happen with script directories in irc clients
2782         # which would only matter if user starts inxi with -! 30 override in irc client
2783         if [[ -L $script_path/$SCRIPT_NAME ]];then
2784                 script_symbolic_start=$script_path/$SCRIPT_NAME
2785                 script_path=$( readlink $script_path/$SCRIPT_NAME )
2786                 script_path=$( dirname $script_path )
2787         fi
2788         local last_modified=$( parse_version_data 'date' ) 
2789         local year_modified=$( gawk '{print $NF}' <<< "$last_modified" )
2790         
2791         print_screen_output "$SCRIPT_NAME $SCRIPT_VERSION_NUMBER-$SCRIPT_PATCH_NUMBER ($last_modified)"
2792         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
2793                 print_screen_output "Program Location: $script_path"
2794                 if [[ -n $script_symbolic_start ]];then
2795                         print_screen_output "Started via symbolic link: $script_symbolic_start"
2796                 fi
2797                 print_lines_basic "0" "" "Website:^http://inxi.goooglecode.com"
2798                 print_lines_basic "0" "" "IRC:^irc.oftc.net channel:^#smxi"
2799                 print_lines_basic "0" "" "Forums:^http://techpatterns.com/forums/forum-33.html"
2800                 print_screen_output " "
2801                 print_lines_basic "0" "" "$SCRIPT_NAME - the universal, portable, system information tool for console and irc."
2802                 print_screen_output " "
2803                 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."
2804                 print_lines_basic "0" "" "Subsequent changes and modifications (after Infobash 3.02): Copyright (C) 2008-$year_modified Scott Rogers, Harald Hope, aka trash80 & h2"
2805                 print_screen_output " "
2806                 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)"
2807         fi
2808 }
2809
2810 ########################################################################
2811 #### MAIN FUNCTIONS
2812 ########################################################################
2813
2814 #### -------------------------------------------------------------------
2815 #### initial startup stuff
2816 #### -------------------------------------------------------------------
2817
2818 # Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION
2819 get_start_client()
2820 {
2821         eval $LOGFS
2822         local Irc_Client_Path='' irc_client_path_lower='' non_native_konvi='' i=''
2823         local B_Non_Native_App='false' pppid='' App_Working_Name=''
2824         local b_qt4_konvi='false' ps_parent=''
2825
2826         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
2827                 IRC_CLIENT='Shell'
2828                 unset IRC_CLIENT_VERSION
2829         # elif [[ -n $PPID ]];then
2830         elif [[ -n $PPID && -f /proc/$PPID/exe ]];then
2831                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2832                         B_OUTPUT_FILTER='true'
2833                 fi
2834                 Irc_Client_Path=$( readlink /proc/$PPID/exe )
2835                 # Irc_Client_Path=$( ps -p $PPID | gawk '!/[[:space:]]*PID/ {print $5}'  )
2836                 # echo $( ps -p $PPID )
2837                 irc_client_path_lower=$( tr '[:upper:]' '[:lower:]' <<< $Irc_Client_Path )
2838                 App_Working_Name=$( basename $irc_client_path_lower )
2839                 # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients
2840                 # report themselves as perl or unknown shell. IE:  when konversation starts inxi
2841                 # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc
2842                 # note: perl can report as: perl5.10.0, so it needs wildcard handling
2843                 case $App_Working_Name in
2844                         # bsd will never use this section
2845                         bash|dash|sh|python*|perl*)     # We want to know who wrapped it into the shell or perl.
2846                                 pppid="$( ps -p $PPID -o ppid --no-headers | sed 's/[[:space:]]//g' )"
2847                                 if [[ -n $pppid && -f /proc/$pppid/exe ]];then
2848                                         Irc_Client_Path="$( readlink /proc/$pppid/exe )"
2849                                         irc_client_path_lower="$( tr '[:upper:]' '[:lower:]' <<< $Irc_Client_Path )"
2850                                         App_Working_Name=$( basename $irc_client_path_lower )
2851                                         B_Non_Native_App='true'
2852                                 fi
2853                                 ;;
2854                 esac
2855                 # sets version number if it can find it
2856                 get_irc_client_version
2857         else
2858                 ## lets look to see if qt4_konvi is the parent.  There is no direct way to tell, so lets infer it.
2859                 ## because $PPID does not work with qt4_konvi, the above case does not work
2860                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2861                         B_OUTPUT_FILTER='true'
2862                 fi
2863                 b_qt4_konvi=$( is_this_qt4_konvi )
2864                 if [[ $b_qt4_konvi == 'true' ]];then
2865                         KONVI=3
2866                         IRC_CLIENT='Konversation'
2867                         IRC_CLIENT_VERSION=" $( konversation -v | gawk '
2868                                 /Konversation:/ {
2869                                         for ( i=2; i<=NF; i++ ) {
2870                                                 if (i == NF) {
2871                                                         print $i
2872                                                 }
2873                                                 else {
2874                                                         printf $i" "
2875                                                 }
2876                                         }
2877                                         exit
2878                                 }' )"
2879                 else
2880                         # this should handle certain cases where it's ssh or some other startup tool
2881                         # that falls through all the other tests
2882                         if [[ $BSD_TYPE != 'bsd' ]];then
2883                                 App_Working_Name=$(ps -p $PPID --no-headers 2>/dev/null | gawk '{print $NF}' )
2884                         else
2885                                 # without --no-headers we need the second line
2886                                 App_Working_Name=$(ps -p $PPID 2>/dev/null | gawk '/^[0-9]+/ {print $5}' )
2887                         fi
2888                         
2889                         if [[ -n $App_Working_Name ]];then
2890                                 Irc_Client_Path=$App_Working_Name
2891                                 B_Non_Native_App='false'
2892                                 get_irc_client_version
2893                                 if [[ -z $IRC_CLIENT ]];then
2894                                         IRC_CLIENT=$App_Working_Name
2895                                 fi
2896                         else
2897                                 IRC_CLIENT="PPID=\"$PPID\" - empty?"
2898                                 unset IRC_CLIENT_VERSION
2899                         fi
2900                 fi
2901         fi
2902
2903         log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID"
2904         eval $LOGFE
2905 }
2906 # note: all variables set in caller so no need to pass
2907 get_irc_client_version()
2908 {
2909         local file_data=''
2910         # replacing loose detection with tight detection, bugs will be handled with app names
2911         # as they appear.
2912         case $App_Working_Name in
2913                 # check for shell first
2914                 bash|dash|sh)
2915                         unset IRC_CLIENT_VERSION
2916                         IRC_CLIENT="Shell wrapper"
2917                         ;;
2918                 # now start on irc clients, alphabetically
2919                 bitchx)
2920                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
2921                         /Version/ {
2922                                 a=tolower($2)
2923                                 gsub(/[()]|bitchx-/,"",a)
2924                                 print a
2925                                 exit
2926                         }
2927                         $2 == "version" {
2928                                 a=tolower($3)
2929                                 sub(/bitchx-/,"",a)
2930                                 print a
2931                                 exit
2932                         }' )"
2933                         B_CONSOLE_IRC='true'
2934                         IRC_CLIENT="BitchX"
2935                         ;;
2936                 finch)
2937                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2938                                 print $2
2939                         }' )"
2940                         B_CONSOLE_IRC='true'
2941                         IRC_CLIENT="Finch"
2942                         ;;
2943                 gaim)
2944                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2945                                 print $2
2946                         }' )"
2947                         IRC_CLIENT="Gaim"
2948                         ;;
2949                 hexchat)
2950                         # the hexchat author decided to make --version/-v return a gtk dialogue box, lol...
2951                         # so we need to read the actual config file for hexchat. Note that older hexchats
2952                         # used xchat config file, so test first for default, then legacy. Because it's possible
2953                         # for this file to be use edited, doing some extra checks here.
2954                         if [[ -f ~/.config/hexchat/hexchat.conf ]];then
2955                                 file_data="$( cat ~/.config/hexchat/hexchat.conf )"
2956                         elif [[ -f  ~/.config/hexchat/xchat.conf ]];then
2957                                 file_data="$( cat ~/.config/hexchat/xchat.conf )"
2958                         fi
2959                         if [[ -n $file_data ]];then
2960                                 IRC_CLIENT_VERSION=$( gawk '
2961                                 BEGIN {
2962                                         IGNORECASE=1
2963                                         FS="="
2964                                 }
2965                                 /^[[:space:]]*version/ {
2966                                         # get rid of the space if present
2967                                         gsub(/[[:space:]]*/, "", $2 )
2968                                         print $2
2969                                         exit # usually this is the first line, no point in continuing
2970                                 }' <<< "$file_data" )
2971                                 
2972                                 IRC_CLIENT_VERSION=" $IRC_CLIENT_VERSION"
2973                         else
2974                                 IRC_CLIENT_VERSION=' N/A'
2975                         fi
2976                         IRC_CLIENT="HexChat"
2977                         ;;
2978                 ircii)
2979                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2980                                 print $3
2981                         }' )"
2982                         B_CONSOLE_IRC='true'
2983                         IRC_CLIENT="ircII"
2984                         ;;
2985                 irssi-text|irssi)
2986                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
2987                                 print $2
2988                         }' )"
2989                         B_CONSOLE_IRC='true'
2990                         IRC_CLIENT="Irssi"
2991                         ;;
2992                 konversation) ## konvi < 1.2 (qt4)
2993                         # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script
2994                         if [[ $B_Non_Native_App == 'true' ]];then  ## true negative is confusing
2995                                 KONVI=2
2996                         else # if native app
2997                                 KONVI=1
2998                         fi
2999                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk '
3000                         /Konversation:/ {
3001                                 for ( i=2; i<=NF; i++ ) {
3002                                         if (i == NF) {
3003                                                 print $i
3004                                         }
3005                                         else {
3006                                                 printf $i" "
3007                                         }
3008                                 }
3009                                 exit
3010                         }' )"
3011
3012                         T=($IRC_CLIENT_VERSION)
3013                         if [[ ${T[0]} == *+* ]];then
3014                                 # < Sho_> locsmif: The version numbers of SVN versions look like this:
3015                                 #         "<version number of last release>+ #<build number", i.e. "1.0+ #3177" ...
3016                                 #         for releases we remove the + and build number, i.e. "1.0" or soon "1.0.1"
3017                                 IRC_CLIENT_VERSION=" CVS $IRC_CLIENT_VERSION"
3018                                 T2="${T[0]/+/}"
3019                         else
3020                                 IRC_CLIENT_VERSION=" ${T[0]}"
3021                                 T2="${T[0]}"
3022                         fi
3023                         # Remove any dots except the first, and make sure there are no trailing zeroes,
3024                         T2=$( echo "$T2" | gawk '{
3025                                 sub(/\./, " ")
3026                                 gsub(/\./, "")
3027                                 sub(/ /, ".")
3028                                 printf("%g\n", $0)
3029                         }' )
3030                         # Since Konversation 1.0, the DCOP interface has changed a bit: dcop "$DCPORT" Konversation ..etc
3031                         # becomes : dcop "$DCPORT" default ... or dcop "$DCPORT" irc ..etc. So we check for versions smaller
3032                         # than 1 and change the DCOP parameter/object accordingly.
3033                         if [[ ${T2} -lt 1 ]];then
3034                                 DCOPOBJ="Konversation"
3035                         fi
3036                         IRC_CLIENT="Konversation"
3037                         ;;
3038                 kopete)
3039                         IRC_CLIENT_VERSION=" $( kopete -v | gawk '
3040                         /Kopete:/ {
3041                                 print $2
3042                                 exit
3043                         }' )"
3044                         IRC_CLIENT="Kopete"
3045                         ;;
3046                 kvirc)
3047                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>&1 | gawk '{
3048                                 for ( i=2; i<=NF; i++) {
3049                                         if ( i == NF ) {
3050                                                 print $i
3051                                         }
3052                                         else {
3053                                                 printf $i" "
3054                                         }
3055                                 }
3056                                 exit
3057                                 }' )"
3058                         IRC_CLIENT="KVIrc"
3059                         ;;
3060                 pidgin)
3061                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3062                                 print $2
3063                         }' )"
3064                         IRC_CLIENT="Pidgin"
3065                         ;;
3066                 quassel*)
3067                         # sample: quassel -v
3068                         # Qt: 4.5.0
3069                         # KDE: 4.2.65 (KDE 4.2.65 (KDE 4.3 >= 20090226))
3070                         # Quassel IRC: v0.4.0 [+60] (git-22effe5)
3071                         # note: early < 0.4.1 quassels do not have -v
3072                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v 2>/dev/null | gawk -F ': ' '
3073                         BEGIN {
3074                                 IGNORECASE=1
3075                                 clientVersion=""
3076                         }
3077                         /Quassel IRC/ {
3078                                 clientVersion = $2
3079                         }
3080                         END {
3081                                 # this handles pre 0.4.1 cases with no -v
3082                                 if ( clientVersion == "" ) {
3083                                         clientVersion = "(pre v0.4.1)"
3084                                 }
3085                                 print clientVersion
3086                         }' )"
3087                         # now handle primary, client, and core. quasselcore doesn't actually
3088                         # handle scripts with exec, but it's here just to be complete
3089                         case $App_Working_Name in
3090                                 quassel)
3091                                         IRC_CLIENT="Quassel [M]"
3092                                         ;;
3093                                 quasselclient)
3094                                         IRC_CLIENT="Quassel"
3095                                         ;;
3096                                 quasselcore)
3097                                         IRC_CLIENT="Quassel (core)"
3098                                         ;;
3099                         esac
3100                         ;;
3101                 weechat-curses)
3102                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v ) "
3103                         B_CONSOLE_IRC='true'
3104                         IRC_CLIENT="Weechat"
3105                         ;;
3106                 xchat-gnome)
3107                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3108                                 print $2
3109                         }' )"
3110                         IRC_CLIENT="X-Chat-Gnome"
3111                         ;;
3112                 xchat)
3113                         IRC_CLIENT_VERSION=" $( $Irc_Client_Path -v | gawk 'NR == 1 {
3114                                 print $2
3115                         }' )"
3116                         IRC_CLIENT="X-Chat"
3117                         ;;
3118                 # then do some perl type searches, do this last since it's a wildcard search
3119                 perl*|ksirc|dsirc)
3120                         unset IRC_CLIENT_VERSION
3121                         # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client
3122                         get_cmdline $PPID
3123                         for (( i=0; i <= $CMDL_MAX; i++ ))
3124                         do
3125                                 case ${A_CMDL[i]} in
3126                                         *dsirc*)
3127                                         IRC_CLIENT="KSirc"
3128                                         # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
3129                                         # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
3130                                         # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
3131                                         # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
3132                                         # dsirc is the program that runs inxi, therefore that is the parent process that we see.
3133                                         # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
3134                                         # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
3135                                         # (KSirc sucks anyway ;)
3136                                         IRC_CLIENT_VERSION=" $( ksirc -v | gawk '
3137                                         /KSirc:/ {
3138                                                 print $2
3139                                                 exit
3140                                         }' )"
3141                                         break
3142                                         ;;
3143                                 esac
3144                         done
3145                         B_CONSOLE_IRC='true'
3146                         set_perl_python_konvi "$App_Working_Name"
3147                         ;;
3148                 python*)
3149                         # B_CONSOLE_IRC='true' # are there even any python type console irc clients? check.
3150                         set_perl_python_konvi "$App_Working_Name"
3151                         ;;
3152                 # then unset, set unknown data
3153                 *)      
3154                         IRC_CLIENT="Unknown : ${Irc_Client_Path##*/}"
3155                         unset IRC_CLIENT_VERSION
3156                         ;;
3157         esac
3158         if [[ $SHOW_IRC -lt 2 ]];then
3159                 unset IRC_CLIENT_VERSION
3160         fi
3161 }
3162
3163 # args: $1 - App_Working_Name
3164 set_perl_python_konvi()
3165 {
3166         if [[ -z $IRC_CLIENT_VERSION ]];then
3167                 # this is a hack to try to show konversation if inxi is running but started via /cmd
3168                 if [[ -n $( grep -i 'konversation' <<< "$Ps_aux_Data" | grep -v 'grep' ) && $B_RUNNING_IN_DISPLAY == 'true' ]];then
3169                         IRC_CLIENT='Konversation'
3170                         IRC_CLIENT_VERSION=" $( konversation --version 2>/dev/null | gawk '/^Konversation/ {print $2}' )"
3171                         B_CONSOLE_IRC='false'
3172                 else
3173                         IRC_CLIENT="Unknown $1 client"
3174                 fi
3175         fi
3176 }
3177
3178 ## try to infer the use of Konversation >= 1.2, which shows $PPID improperly
3179 ## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running,
3180 ## and all other irc clients are not running.  
3181 is_this_qt4_konvi()
3182 {
3183         local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' 
3184         local konvi='' konvi_qt4_ver='' b_is_qt4=''
3185         
3186         # fringe cases can throw error, always if untested app, use 2>/dev/null after testing if present
3187         if [[ $B_QDBUS == 'true' ]];then
3188                 konvi_dbus_exist=$( qdbus 2>/dev/null | grep "org.kde.konversation" )
3189         fi
3190         # sabayon uses /usr/share/apps/konversation as path
3191         if [[ -n $konvi_dbus_exist ]] && [[ -e /usr/share/kde4/apps/konversation || -e  /usr/share/apps/konversation ]]; then
3192                 konvi_pid=$( ps -A | gawk 'BEGIN{IGNORECASE=1} /konversation/ { print $1 }' ) 
3193                 konvi_home_dir=$( readlink /proc/$konvi_pid/exe )
3194                 konvi=$( echo $konvi_home_dir | sed "s/\// /g" )
3195                 konvi=($konvi)
3196
3197                 if [[ ${konvi[2]} == 'konversation' ]];then     
3198                         konvi_qt4_ver=$( konversation -v | grep -i 'konversation' )
3199                         # note: we need to change this back to a single dot number, like 1.3, not 1.3.2
3200                         konvi_qt4_client=$( echo "$konvi_qt4_ver" | gawk '{ print $2 }' | cut -d '.' -f 1,2 )
3201
3202                         if [[ $konvi_qt4_client > 1.1 ]]; then
3203                                 b_is_qt4='true'
3204                         fi
3205                 fi
3206         else
3207                 konvi_qt4="qt3"
3208                 b_is_qt4='false'
3209         fi
3210         log_function_data "b_is_qt4: $b_is_qt4"
3211         echo $b_is_qt4
3212         ## for testing this module
3213         #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]}"
3214 }
3215
3216 # This needs some cleanup and comments, not quite understanding what is happening, although generally output is known
3217 # Parse the null separated commandline under /proc/<pid passed in $1>/cmdline
3218 # args: $1 - $PPID
3219 get_cmdline()
3220 {
3221         eval $LOGFS
3222         local i=0 ppid=$1
3223
3224         if [[ ! -e /proc/$ppid/cmdline ]];then
3225                 echo 0
3226                 return
3227         fi
3228         ##print_screen_output "Marker"
3229         ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)"
3230         unset A_CMDL
3231         ## note: need to figure this one out, and ideally clean it up and make it readable
3232         while read -d $'\0' L && [[ $i -lt 32 ]]
3233         do
3234                 A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ##
3235         done < /proc/$ppid/cmdline
3236         ##print_screen_output "\$i='$i'"
3237         if [[ $i -eq 0 ]];then
3238                 A_CMDL[0]=$(< /proc/$ppid/cmdline)
3239                 if [[ -n ${A_CMDL[0]} ]];then
3240                         i=1
3241                 fi
3242         fi
3243         CMDL_MAX=$i
3244         log_function_data "CMDL_MAX: $CMDL_MAX"
3245         eval $LOGFE
3246 }
3247
3248 #### -------------------------------------------------------------------
3249 #### get data types
3250 #### -------------------------------------------------------------------
3251 ## create array of sound cards installed on system, and if found, use asound data as well
3252 get_audio_data()
3253 {
3254         eval $LOGFS
3255         local i='' alsa_data='' audio_driver='' device_count='' temp_array=''
3256
3257         IFS=$'\n'
3258         # this first step handles the drivers for cases where the second step fails to find one
3259         device_count=$( echo "$Lspci_v_Data" | grep -iEc '(multimedia audio controller|audio device)' )
3260         if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3261                 audio_driver=$( gawk -F ']: ' '
3262                 BEGIN {
3263                         IGNORECASE=1
3264                 }
3265                 # filtering out modems and usb devices like webcams, this might get a
3266                 # usb audio card as well, this will take some trial and error
3267                 $0 !~ /modem|usb|webcam/ {
3268                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3269                         gsub(/^ +| +$/,"",driver)
3270                         if ( driver != "" ){
3271                                 print driver
3272                         }
3273                 }' $FILE_ASOUND_DEVICE ) 
3274                 log_function_data 'cat' "$FILE_ASOUND_DEVICE"
3275         fi
3276
3277         # this is to safeguard against line breaks from results > 1, which if inserted into following
3278         # array will create a false array entry. This is a hack, not a permanent solution.
3279         audio_driver=$( echo $audio_driver )
3280         # now we'll build the main audio data, card name, driver, and port. If no driver is found,
3281         # and if the first method above is not null, and one card is found, it will use that instead.
3282         A_AUDIO_DATA=( $( echo "$Lspci_v_Data" | gawk -F ': ' -v audioDriver="$audio_driver" '
3283         BEGIN {
3284                 IGNORECASE=1
3285         }
3286         /multimedia audio controller|audio device/ {
3287                 audioCard=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
3288                 # The doublequotes are necessary because of the pipes in the variable.
3289                 gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard)
3290                 gsub(/,/, " ", audioCard)
3291                 gsub(/^ +| +$/, "", audioCard)
3292                 gsub(/ [ \t]+/, " ", audioCard)
3293                 aPciBusId[audioCard] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
3294                 cards[audioCard]++
3295
3296                 # loop until you get to the end of the data block
3297                 while (getline && !/^$/) {
3298                         gsub( /,/, "", $0 )
3299                         if (/driver in use/) {
3300                                 drivers[audioCard] = drivers[audioCard] gensub( /(.*): (.*)/ ,"\\2", "g" ,$0 ) ""
3301                         }
3302                         else if (/kernel modules:/) {
3303                                 modules[audioCard] = modules[audioCard] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
3304                         }
3305                         else if (/I\/O/) {
3306                                 portsTemp = gensub(/\t*I\/O ports at (.*) \[.*\]/,"\\1","g",$0)
3307                                 ports[audioCard] = ports[audioCard] portsTemp " "
3308                         }
3309                 }
3310         }
3311
3312         END {
3313                 j=0
3314                 for (i in cards) {
3315                         useDrivers=""
3316                         useModules=""
3317                         usePorts=""
3318                         usePciBusId=""
3319                          
3320                         if (cards[i]>1) {
3321                                 a[j]=cards[i]"x "i
3322                                 if (drivers[i] != "") {
3323                                         useDrivers=drivers[i]
3324                                 }
3325                         }
3326                         else {
3327                                 a[j]=i
3328                                 # little trick here to try to catch the driver if there is
3329                                 # only one card and it was null, from the first test of asound/cards
3330                                 if (drivers[i] != "") {
3331                                         useDrivers=drivers[i]
3332                                 }
3333                                 else if ( audioDriver != "" ) {
3334                                         useDrivers=audioDriver
3335                                 }
3336                         }
3337                         if (ports[i] != "") {
3338                                 usePorts = ports[i]
3339                         }
3340                         if (modules[i] != "" ) {
3341                                 useModules = modules[i]
3342                         }
3343                         if ( aPciBusId[i] != "" ) {
3344                                 usePciBusId = aPciBusId[i]
3345                         }
3346                         # create array primary item for master array
3347                         sub( / $/, "", usePorts ) # clean off trailing whitespace
3348                         print a[j] "," useDrivers "," usePorts "," useModules "," usePciBusId
3349                         j++
3350                 }
3351         }') )
3352
3353         # in case of failure of first check do this instead
3354         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
3355                 A_AUDIO_DATA=( $( gawk -F ']: ' '
3356                 BEGIN {
3357                         IGNORECASE=1
3358                 }
3359                 $1 !~ /modem/ && $2 !~ /modem/ {
3360                         card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 )
3361                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
3362                         if ( card != "" ){
3363                                 print card","driver
3364                         }
3365                 }' $FILE_ASOUND_DEVICE ) )
3366         fi
3367         IFS="$ORIGINAL_IFS"
3368         get_audio_usb_data
3369         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
3370         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then
3371                 A_AUDIO_DATA[0]='Failed to Detect Sound Card!'
3372         fi
3373         temp_array=${A_AUDIO_DATA[@]}
3374         log_function_data "A_AUDIO_DATA: $temp_array"
3375
3376         eval $LOGFE
3377 }
3378 # alsa usb detection by damentz
3379
3380 get_audio_usb_data()
3381 {
3382         eval $LOGFS
3383         local usb_proc_file='' array_count='' usb_data='' usb_id='' lsusb_path='' lsusb_data=''
3384         local temp_array=''
3385         
3386         IFS=$'\n'
3387         lsusb_path=$( type -p lsusb )
3388         if [[ -n $lsusb_path ]];then
3389                 lsusb_data=$( $lsusb_path 2>/dev/null )
3390         fi
3391         log_function_data 'raw' "usb_data:\n$lsusb_data"
3392         if [[ -n $lsusb_data ]];then
3393                 # for every sound card symlink in /proc/asound - display information about it
3394                 for usb_proc_file in /proc/asound/*
3395                 do
3396                         # If the file is a symlink, and contains an important usb exclusive file: continue
3397                         if [[ -L $usb_proc_file && -e $usb_proc_file/usbid  ]]; then
3398                                 # find the contents of usbid in lsusb and print everything after the 7th word on the
3399                                 # corresponding line. Finally, strip out commas as they will change the driver :)
3400                                 usb_id=$( cat $usb_proc_file/usbid )
3401                                 usb_data=$( grep "$usb_id" <<< "$lsusb_data" )
3402                                 if [[ -n $usb_data && -n $usb_id ]];then
3403                                         usb_data=$( gawk '
3404                                         BEGIN {
3405                                                 IGNORECASE=1
3406                                                 string=""
3407                                                 separator=""
3408                                         }
3409                                         {
3410                                                 gsub( /,/, " ", $0 )
3411                                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
3412                                                 gsub(/ [ \t]+/, " ", $0)
3413                                                 for ( i=7; i<= NF; i++ ) {
3414                                                         string = string separator $i
3415                                                         separator = " "
3416                                                 }
3417                                                 if ( $2 != "" ){
3418                                                         sub(/:/,"", $4)
3419                                                         print string ",USB Audio,,," $2 "-" $4 "," $6
3420                                                 }
3421                                         }' <<< "$usb_data" )
3422                                 fi
3423                                 # this method is interesting, it shouldn't work but it does
3424                                 #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,USB Audio,," )
3425                                 # but until we learn why the above worked, I'm using this one, which is safer
3426                                 if [[ -n $usb_data ]];then
3427                                         array_count=${#A_AUDIO_DATA[@]}
3428                                         A_AUDIO_DATA[$array_count]="$usb_data"
3429                                 fi
3430                         fi
3431                 done
3432         fi
3433         IFS="$ORIGINAL_IFS"
3434         temp_array=${A_AUDIO_DATA[@]}
3435         log_function_data "A_AUDIO_DATA: $temp_array"
3436         
3437         eval $LOGFE
3438 }
3439
3440 get_audio_alsa_data()
3441 {
3442         eval $LOGFS
3443         local alsa_data='' temp_array=''
3444
3445         # now we'll get the alsa data if the file exists
3446         if [[ $B_ASOUND_VERSION_FILE == 'true' ]];then
3447                 IFS=","
3448                 A_ALSA_DATA=( $( 
3449                 gawk '
3450                         BEGIN {
3451                                 IGNORECASE=1
3452                                 alsa=""
3453                                 version=""
3454                         }
3455                         # some alsa strings have the build date in (...)
3456                         # remove trailing . and remove possible second line if compiled by user
3457                         $0 !~ /compile/ {
3458                                 gsub( /Driver | [(].*[)]|\.$/,"",$0 )
3459                                 gsub(/,/, " ", $0)
3460                                 gsub(/^ +| +$/, "", $0)
3461                                 gsub(/ [ \t]+/, " ", $0)
3462                                 sub(/Advanced Linux Sound Architecture/, "ALSA", $0)
3463                                 if ( $1 == "ALSA" ){
3464                                         alsa=$1
3465                                 }
3466                                 version=$NF
3467                                 print alsa "," version
3468                         }' $FILE_ASOUND_VERSION ) )
3469                 IFS="$ORIGINAL_IFS"
3470                 log_function_data 'cat' "$FILE_ASOUND_VERSION"
3471         fi
3472         temp_array=${A_ALSA_DATA[@]}
3473         log_function_data "A_ALSA_DATA: $temp_array"
3474         eval $LOGFE
3475 }
3476
3477 ## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text
3478 ## return value cpu core count string, this helps resolve the multi redundant lines of old style output
3479 get_cpu_core_count()
3480 {
3481         eval $LOGFS
3482         local cpu_physical_count='' cpu_core_count='' cpu_type='' cpu_alpha_count=''
3483         if [[ $B_CPUINFO_FILE == 'true' ]]; then
3484                 # load the A_CPU_TYPE_PCNT_CCNT core data array
3485                 get_cpu_ht_multicore_smp_data
3486                 ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10)
3487                 # count the number of processors given
3488                 cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]}
3489                 cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]}
3490                 cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]}
3491
3492                 # match the numberic value to an alpha value
3493                 cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
3494                 
3495                 # create array, core count integer; core count string
3496                 # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" )
3497                 A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" )
3498         elif [[ -n $BSD_TYPE ]];then
3499                 local gawk_fs=': '
3500         
3501                 if [[ $BSD_VERSION == 'openbsd' ]];then
3502                         gawk_fs='='
3503                 fi
3504                 cpu_core_count=$( gawk -F "$gawk_fs" '
3505                 # note: on openbsd can also be hw.ncpufound so exit after first
3506                 /^hw.ncpu/ {
3507                         print $NF
3508                         exit
3509                 }' <<< "$Sysctl_a_Data" )
3510                 if [[ -n $( grep -E '^[0-9]+$' <<< "$cpu_core_count" ) ]];then
3511                         cpu_alpha_count=$( get_cpu_core_count_alpha "$cpu_core_count" )
3512                         if [[ $cpu_core_count -gt 1 ]];then
3513                                 cpu_type='SMP'
3514                         fi
3515                 fi
3516                 cpu_physical_count=1
3517                 A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" )
3518         fi
3519         temp_array=${A_CPU_CORE_DATA[@]}
3520         log_function_data "A_CPU_CORE_DATA: $temp_array"
3521         eval $LOGFE
3522 }
3523
3524 # args: $1 - integer core count
3525 get_cpu_core_count_alpha()
3526 {
3527         eval $LOGFS
3528         local cpu_alpha_count=''
3529         
3530         case $1 in
3531                 1) cpu_alpha_count='Single';;
3532                 2) cpu_alpha_count='Dual';;
3533                 3) cpu_alpha_count='Triple';;
3534                 4) cpu_alpha_count='Quad';;
3535                 5) cpu_alpha_count='Penta';;
3536                 6) cpu_alpha_count='Hexa';;
3537                 7) cpu_alpha_count='Hepta';;
3538                 8) cpu_alpha_count='Octa';;
3539                 9) cpu_alpha_count='Ennea';;
3540                 10) cpu_alpha_count='Deca';;
3541                 *) cpu_alpha_count='Multi';;
3542         esac
3543         
3544         echo $cpu_alpha_count
3545         
3546         eval $LOGFE
3547 }
3548
3549 ## main cpu data collector
3550 get_cpu_data()
3551 {
3552         eval $LOGFS
3553         local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' temp_array=''
3554         local bsd_cpu_flags=''
3555
3556         if [[ $B_CPUINFO_FILE == 'true' ]];then
3557                 # stop script for a bit to let cpu slow down before parsing cpu /proc file
3558                 sleep $CPU_SLEEP
3559                 IFS=$'\n'
3560                 A_CPU_DATA=( $( 
3561                 gawk -F': ' '
3562                 BEGIN {
3563                         IGNORECASE=1
3564                         # need to prime nr for arm cpus, which do not have processor number output in some cases
3565                         nr = 0
3566                         count = 0
3567                         bArm = "false"
3568                 }
3569                 # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+
3570                 # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES!
3571                 # Therefore PATCH to use [ \t]+ when TESTING!
3572                 /^processor[ \t]+:/ {
3573                         gsub(/,/, " ", $NF)
3574                         gsub(/^ +| +$/, "", $NF)
3575                         if ( $NF ~ "^[0-9]+$" ) {
3576                                 nr = $NF
3577                         }
3578                         else {
3579                                 if ( $NF ~ "^ARM" ) {
3580                                         bArm = "true"
3581                                 }
3582                                 count += 1
3583                                 nr = count - 1
3584                                 cpu[nr, "model"] = $NF
3585                         }
3586                 }
3587
3588                 /^model name|^cpu\t+:/ {
3589                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
3590                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
3591                         gsub(/,/, " ", $NF)
3592                         gsub(/^ +| +$/, "", $NF)
3593                         gsub(/ [ \t]+/, " ", $NF)
3594                         cpu[nr, "model"] = $NF
3595                         if ( $NF ~ "^ARM" ) {
3596                                 bArm = "true"
3597                         }
3598                 }
3599
3600                 /^cpu MHz|^clock\t+:/ {
3601                         if (!min) {
3602                                 min = $NF
3603                         }
3604                         else {
3605                                 if ($NF < min) {
3606                                         min = $NF
3607                                 }
3608                         }
3609
3610                         if ($NF > max) {
3611                                 max = $NF
3612                         }
3613                         gsub(/MHZ/,"",$NF) ## clears out for cell cpu
3614                         gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros
3615                         cpu[nr, "speed"] = $NF
3616                 }
3617
3618                 /^cache size/ {
3619                         cpu[nr, "cache"] = $NF
3620                 }
3621
3622                 /^flags|^features/ {
3623                         cpu[nr, "flags"] = $NF
3624                         # not all ARM cpus show ARM in model name
3625                         if ( $1 ~ /^features/ ) {
3626                                 bArm = "true"
3627                         }
3628                 }
3629
3630                 /^bogomips/ {
3631                         cpu[nr, "bogomips"] = $NF
3632                 }
3633
3634                 /vendor_id/ {
3635                         gsub(/genuine|authentic/,"",$NF)
3636                         cpu[nr, "vendor"] = tolower( $NF )
3637                 }
3638
3639                 END {
3640                         #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that
3641                         for ( i = 0; i <= nr; i++ ) {
3642                                 # note: assuming bogomips for arm at 1 x clock
3643                                 # http://en.wikipedia.org/wiki/BogoMips ARM could change so watch this
3644                                 # maybe add:  && bArm == "true" but I think most of the bogomips roughly equal cpu speed if not amd/intel
3645                                 if ( cpu[i, "bogomips"] != "" && cpu[i, "speed"] == "" ) {
3646                                         cpu[i, "speed"] = cpu[i, "bogomips"]
3647                                 }
3648                                 print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] ","  cpu[nr, "vendor"] "," bArm
3649                         }
3650                         # this is / was used in inxi short output only, but when it is N/A, need to use the previous array
3651                         # value, from above, the actual speed that is, for short output, key 0.
3652                         if (!min) {
3653                                 print "N/A"
3654                                 exit
3655                         }
3656                         else {
3657                                 if (min != max) {
3658                                         printf("Min:%s%s Max:%s%s\n", min, "Mhz", max, "Mhz")
3659                                 }
3660                                 else {
3661                                         printf("%s %s\n", max, "Mhz")
3662                                 }
3663                         }
3664                 }
3665                 ' $FILE_CPUINFO ) )
3666                 IFS="$ORIGINAL_IFS"
3667                 log_function_data 'cat' "$FILE_CPUINFO"
3668         elif [[ -n $BSD_TYPE ]];then
3669                 get_cpu_data_bsd
3670         fi
3671         
3672         temp_array=${A_CPU_DATA[@]}
3673         log_function_data "A_CPU_DATA: $temp_array"
3674 #       echo ta: ${temp_array[@]}
3675         eval $LOGFE
3676 #       echo getMainCpu: ${[@]}
3677 }
3678
3679 get_cpu_data_bsd()
3680 {
3681         eval $LOGFS
3682
3683         local bsd_cpu_flags=$( get_cpu_flags_bsd )
3684         local gawk_fs=': '
3685         
3686         if [[ $BSD_VERSION == 'openbsd' ]];then
3687                 gawk_fs='='
3688         fi
3689                 
3690         IFS=$'\n'
3691         A_CPU_DATA=( $( 
3692         gawk -F "$gawk_fs" -v cpuFlags="$bsd_cpu_flags" '
3693         BEGIN {
3694                 IGNORECASE=1
3695                 cpuModel=""
3696                 cpuClock=""
3697                 cpuCache=""
3698                 cpuBogomips=""
3699                 cpuVendor=""
3700         }
3701         /^hw.model/ {
3702                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
3703                 gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
3704                 sub(//,"",$NF)
3705                 sub(/[a-z]+-core/, "", $NF )
3706                 gsub(/^ +| +$|\"/, "", $NF)
3707                 gsub(/ [ \t]+/, " ", $NF)
3708                 cpuModel=$NF
3709                 if ( cpuClock != "" ) {
3710                         exit
3711                 }
3712         }
3713         /^hw.(clock|cpuspeed)/ {
3714                 cpuClock=$NF
3715                 if ( cpuModel != "" ) {
3716                         exit
3717                 }
3718         }
3719         END {
3720                 print cpuModel "," cpuClock "," cpuCache "," cpuFlags "," cpuBogomips ","  cpuVendor
3721                 print "N/A"
3722         }' <<< "$Sysctl_a_Data" ) )
3723         IFS="$ORIGINAL_IFS"
3724         
3725         eval $LOGFE
3726 }
3727
3728 get_cpu_flags_bsd()
3729 {
3730         eval $LOGFS
3731         
3732         local cpu_flags=$( gawk -F '=' '
3733         BEGIN {
3734                 IGNORECASE=1
3735                 cpuFlags=""
3736         }
3737         /^CPU:/ {
3738                 while ( getline && !/memory/  ) {
3739                         if ( $1 ~ /Features/ ) {
3740                                 # clean up odd stuff like <b23>
3741                                 gsub(/<[a-z0-9]+>/,"", $2)
3742                                 # all the flags are contained within < ... > on freebsd at least
3743                                 gsub(/.*<|>.*/,"", $2)
3744                                 gsub(/,/," ", $2)
3745                                 cpuFlags = cpuFlags " " $2
3746                         }
3747                 }
3748                 cpuFlags=tolower(cpuFlags)
3749                 print cpuFlags
3750                 exit
3751         }' <<< "$Dmesg_Boot_Data" )
3752         
3753         echo $cpu_flags
3754         log_function_data "$cpu_flags"
3755         eval $LOGFE
3756 }
3757
3758 ## this is for counting processors and finding HT types
3759 get_cpu_ht_multicore_smp_data()
3760 {
3761         eval $LOGFS
3762         # in /proc/cpuinfo
3763         local temp_array=''
3764         
3765         # note: known bug with xeon intel, they show a_core_id/physical_id as 0 for ht 4 core
3766         if [[ $B_CPUINFO_FILE == 'true' ]]; then
3767                 A_CPU_TYPE_PCNT_CCNT=( $(
3768                 gawk '
3769                 BEGIN {
3770                         FS=": "
3771                         IGNORECASE = 1
3772                         num_of_cores = 0
3773                         num_of_processors = 0
3774                         num_of_physical_cpus = 0
3775                         cpu_core_count = 0
3776                         siblings = 0
3777                         # these 3 arrays cannot be declared because that sets the first element
3778                         # but leaving this here so that we avoid doing that in the future
3779                         # a_core_id = ""
3780                         # a_processor_id = ""
3781                         # a_physical_id = ""
3782                         cpu_type = "-"
3783                         # note: we need separate iterators because some cpuinfo data has only
3784                         # processor, no core id or phys id
3785                         proc_iter = 0
3786                         core_iter = "" # set from actual NF data
3787                         phys_iter = "" # set from actual NF data
3788                         # needed to handle arm cpu, no processor number cases
3789                         arm_count = 0
3790                         nr = 0
3791                         bArm = "false"
3792                         bXeon = "false"
3793                 }
3794                 # hack to handle xeons which can have buggy /proc/cpuinfo files
3795                 /^model name/ && ( $0 ~ /Xeon/ ) {
3796                         bXeon = "true"
3797                 }
3798                 # only do this once since sibling count does not change. 
3799                 /^siblings/ && ( bXeon == "true" ) && ( siblings == 0 ) {
3800                         gsub(/[^0-9]/,"",$NF)
3801                         if ( $NF != "" ) {
3802                                 siblings = $NF
3803                         }
3804                 }
3805                 # array of logical processors, both HT and physical
3806                 
3807                 /^processor/ {
3808                         gsub(/,/, " ", $NF)
3809                         gsub(/^ +| +$/, "", $NF)
3810                         if ( $NF ~ "^[0-9]+$" ) {
3811                                 a_processor_id[proc_iter] = $NF
3812                                 proc_iter++
3813                         }
3814                         else {
3815                                 # note, for dual core, this can be off by one because the first
3816                                 # line says: Processor : Arm.. but subsequent say: processor : 0 and so on as usual
3817                                 if ( $NF ~ "^ARM" ) {
3818                                         bArm = "true"
3819                                 }
3820                                 arm_count += 1
3821                                 nr = arm_count - 1
3822                                 # note: do not iterate because new ARM syntax puts cpu in processsor : 0 syntax
3823                                 a_processor_id[proc_iter] = nr
3824                         }
3825                 }
3826                 
3827                 # array of physical cpu ids, note, this will be unset for vm cpus in many cases
3828                 # because they have no physical cpu, so we cannot assume this will be here.
3829                 /^physical/ {
3830                         phys_iter = $NF
3831                         a_physical_id[phys_iter] = $NF
3832                 }
3833                 # array of core ids, again, here we may have HT, so we need to create an array of the
3834                 # actual core ids. As With physical, we cannot assume this will be here in a vm
3835                 /^core id/ {
3836                         core_iter = $NF
3837                         a_core_id[core_iter] = $NF
3838                 }
3839                 # this will be used to fix an intel glitch if needed, cause, intel
3840                 # sometimes reports core id as the same number for each core, 
3841                 # so if cpu cores shows greater value than number of cores, use this. 
3842                 /^cpu cores/ {
3843                         cpu_core_count = $NF
3844                 }
3845                 END {
3846                         ##      Look thru the array and filter same numbers.
3847                         ##      only unique numbers required
3848                         ##      this is to get an accurate count
3849                         ##      we are only concerned with array length
3850                         i = 0
3851                         ## count unique processors ##
3852                         # note, this fails for intel cpus at times
3853                         for ( i in a_processor_id ) {
3854                                 num_of_processors++
3855                         }
3856                         i = 0
3857                         ## count unique physical cpus ##
3858                         for ( i in a_physical_id ) {
3859                                 num_of_physical_cpus++
3860                         }
3861                         
3862                         i = 0
3863                         ## count unique cores ##
3864                         for ( i in a_core_id ) {
3865                                 num_of_cores++
3866                         }
3867                         # xeon may show wrong core / physical id count, if it does, fix it. A xeon
3868                         # may show a repeated core id : 0 which gives a fake num_of_cores=1
3869                         if ( bXeon == "true" && num_of_cores == 1 && siblings > 1 ) {
3870                                 num_of_cores = siblings/2
3871                         }
3872                         # final check, override the num of cores value if it clearly is wrong
3873                         # and use the raw core count and synthesize the total instead of real count
3874                         if ( ( num_of_cores == 0 ) && ( cpu_core_count * num_of_physical_cpus > 1 ) ) {
3875                                 num_of_cores = cpu_core_count * num_of_physical_cpus
3876                         }
3877                         # last check, seeing some intel cpus and vms with intel cpus that do not show any
3878                         # core id data at all, or siblings.
3879                         if ( num_of_cores == 0 && num_of_processors > 0 ) {
3880                                 num_of_cores = num_of_processors
3881                         }
3882                         # ARM/vm cpu fix, if no physical or core found, use count of 1 instead
3883                         if ( num_of_physical_cpus == 0 ) {
3884                                 num_of_physical_cpus = 1
3885                         }
3886 #                       print "NoCpu: " num_of_physical_cpus
3887 #                       print "NoCores: " num_of_cores
3888 #                       print "NoProc:" num_of_processors
3889 #                       print "CpuCoreCount:" cpu_core_count
3890                         ####################################################################
3891                         #                               algorithm
3892                         # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT)
3893                         # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
3894                         # if > 1 processor && processor ids (physical id) > 1 then Multiple Processors (SMP)
3895                         # if = 1 processor then single core/processor Uni-Processor (UP)
3896                         if ( num_of_processors > 1 || ( bXeon == "true" && siblings > 0 ) ) {
3897                                 # non-multicore HT
3898                                 if ( num_of_processors == (num_of_cores * 2) ) {
3899                                         cpu_type = cpu_type "HT-"
3900                                 }
3901                                 else if ( bXeon == "true" && siblings > 1 ) {
3902                                         cpu_type = cpu_type "HT-"
3903                                 }
3904                                 # non-HT multi-core or HT multi-core
3905                                 if (( num_of_processors == num_of_cores) || ( num_of_physical_cpus < num_of_cores)) {
3906                                         cpu_type = cpu_type "MCP-"
3907                                 }
3908                                 # >1 cpu sockets active
3909                                 if ( num_of_physical_cpus > 1 ) {
3910                                         cpu_type = cpu_type "SMP-"
3911                                 }
3912                         } 
3913                         else {
3914                                 cpu_type = cpu_type "UP-"
3915                         }                       
3916                         
3917                         print cpu_type " " num_of_physical_cpus " " num_of_cores 
3918                 }
3919                 ' $FILE_CPUINFO ) )
3920         fi
3921         temp_array=${A_CPU_TYPE_PCNT_CCNT[@]}
3922         log_function_data "A_CPU_TYPE_PCNT_CCNT: $temp_array"
3923         eval $LOGFE
3924 }
3925
3926 # Detect desktop environment in use, initial rough logic from: compiz-check
3927 # http://forlong.blogage.de/entries/pages/Compiz-Check
3928 # NOTE $XDG_CURRENT_DESKTOP envvar is not reliable, but it shows certain desktops better.
3929 # most desktops are not using it as of 2014-01-13 (KDE, UNITY, LXDE. Not Gnome)
3930 get_desktop_environment()
3931 {
3932         eval $LOGFS
3933         
3934         # set the default, this function only runs in X, if null, don't print data out
3935         local desktop_environment='' xprop_root=''
3936         local version='' version_data='' toolkit=''
3937
3938         # works on 4, assume 5 will id the same, why not, no need to update in future
3939         # KDE_SESSION_VERSION is the integer version of the desktop
3940         if [[ $XDG_CURRENT_DESKTOP == 'KDE' || -n $KDE_SESSION_VERSION ]]; then
3941                 # note the command is actually like, kded4 --version, so we construct it
3942                 version_data=$( kded$KDE_SESSION_VERSION --version 2>/dev/null )
3943                 version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
3944                 if [[ -z $version ]];then
3945                         version=$KDE_SESSION_VERSION
3946                 fi
3947                 if [[ $B_EXTRA_DATA == 'true' ]];then
3948                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3949                         if [[ -n $toolkit ]];then
3950                                 version="$version (Qt $toolkit)"
3951                         fi
3952                 fi
3953                 desktop_environment="KDE"
3954         # KDE_FULL_SESSION property is only available since KDE 3.5.5.
3955         # src: http://humanreadable.nfshost.com/files/startkde
3956         elif [[ $KDE_FULL_SESSION == 'true' ]]; then
3957                 version_data=$( kded --version 2>/dev/null )
3958                 version=$( grep -si '^KDE:' <<< "$version_data" | gawk '{print $2}' )
3959                 # version=$( get_de_app_version 'kded' '^KDE:' '2' )
3960                 if [[ -z $version ]];then
3961                         version='3.5'
3962                 fi
3963                 if [[ $B_EXTRA_DATA == 'true' ]];then
3964                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3965                         if [[ -n $toolkit ]];then
3966                                 version="$version (Qt $toolkit)"
3967                         fi
3968                 fi
3969                 desktop_environment="KDE"
3970         elif [[ $XDG_CURRENT_DESKTOP == 'Unity' ]];then
3971                 version=$( get_de_app_version 'unity' '^unity' '2' )
3972                 # not certain cinn will always have version, so keep output right if not
3973                 if [[ -n $version ]];then
3974                         version="$version "
3975                 fi
3976                 if [[ $B_EXTRA_DATA == 'true' ]];then
3977                         toolkit=$( get_de_gtk_data )
3978                         if [[ -n $toolkit ]];then
3979                                 version="${version}(Gtk ${toolkit})"
3980                         fi
3981                 fi
3982                 desktop_environment="Unity"
3983         fi
3984         # did we find it? If not, start the xprop tests
3985         if [[ -z $desktop_environment ]];then
3986                 if [[ -n $( type -p xprop ) ]];then
3987                         xprop_root="$( xprop -root 2>/dev/null )"
3988                 fi
3989                 # note that cinnamon split from gnome, and and can now be id'ed via xprop,
3990                 # but it will still trigger the next gnome true case, so this needs to go before gnome test
3991                 # eventually this needs to be better organized so all the xprop tests are in the same
3992                 # section, but this is good enough for now.
3993                 if [[ -n $xprop_root && -n $( grep -is '^_MUFFIN' <<< "$xprop_root" ) ]];then
3994                         version=$( get_de_app_version 'cinnamon' '^cinnamon' '2' )
3995                         # not certain cinn will always have version, so keep output right if not
3996                         if [[ -n $version ]];then
3997                                 version="$version "
3998                         fi
3999                         if [[ $B_EXTRA_DATA == 'true' ]];then
4000                                 toolkit=$( get_de_gtk_data )
4001                                 if [[ -n $toolkit ]];then
4002                                         version="${version}(Gtk ${toolkit})"
4003                                 fi
4004                         fi
4005                         desktop_environment="Cinnamon"
4006                 elif [[ -n $xprop_root && -n $( grep -is '^_MARCO' <<< "$xprop_root" ) ]];then
4007                         version=$( get_de_app_version 'mate-about' '^MATE[[:space:]]DESKTOP' 'NF' )
4008                         # not certain cinn/mate will always have version, so keep output right if not
4009                         if [[ -n $version ]];then
4010                                 version="$version "
4011                         fi
4012                         if [[ $B_EXTRA_DATA == 'true' ]];then
4013                                 toolkit=$( get_de_gtk_data )
4014                                 if [[ -n $toolkit ]];then
4015                                         version="${version}(Gtk ${toolkit})"
4016                                 fi
4017                         fi
4018                         desktop_environment="MATE"
4019                 # note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out
4020                 # https://bugzilla.gnome.org/show_bug.cgi?id=542880
4021                 elif [[ -n $GNOME_DESKTOP_SESSION_ID ]]; then
4022                         if [[ -n $( type -p gnome-shell ) ]];then
4023                                 version=$( get_de_app_version 'gnome-shell' 'gnome' '3' )
4024                         elif [[ -n $( type -p gnome-about ) ]];then
4025                                 version=$( get_de_app_version 'gnome-about' 'gnome' '3' )
4026                         fi
4027                         if [[ $B_EXTRA_DATA == 'true' ]];then
4028                                 toolkit=$( get_de_gtk_data )
4029                                 if [[ -n $toolkit ]];then
4030                                         version="$version (Gtk $toolkit)"
4031                                 fi
4032                         fi
4033                         desktop_environment="Gnome"
4034                 fi
4035                 if [[ -z $desktop_environment ]];then
4036                 # now that the primary ones have been handled, next is to find the ones with unique
4037                 # xprop detections possible
4038                         if [[ -n $xprop_root ]];then
4039                                 # String: "This is xfdesktop version 4.2.12"
4040                                 # alternate: xfce4-about --version > xfce4-about 4.10.0 (Xfce 4.10)
4041                                 if [[ -n $( grep -Eis '\"xfce4\"' <<< "$xprop_root" ) ]];then
4042                                         version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
4043                                         # arch linux reports null, so use alternate if null
4044                                         if [[ -z $version ]];then
4045                                                 version=$( get_de_app_version 'xfce4-panel' '^xfce4-panel' '2' )
4046                                                 if [[ -z $version ]];then
4047                                                         version='4'
4048                                                 fi
4049                                         fi
4050                                         if [[ $B_EXTRA_DATA == 'true' ]];then
4051                                                 toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
4052                                                 if [[ -n $toolkit ]];then
4053                                                         version="$version (Gtk $toolkit)"
4054                                                 fi
4055                                         fi
4056                                         desktop_environment="Xfce"
4057                                 # when 5 is released, the string may need updating
4058                                 elif [[ -n $( grep -is '\"xfce5\"' <<< "$xprop_root" ) ]];then
4059                                         version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
4060                                         # arch linux reports null, so use alternate if null
4061                                         if [[ -z $version ]];then
4062                                                 version=$( get_de_app_version 'xfce5-panel' '^xfce5-panel' '2' )
4063                                                 if [[ -z $version ]];then
4064                                                         version='5'
4065                                                 fi
4066                                         fi
4067                                         if [[ $B_EXTRA_DATA == 'true' ]];then
4068                                                 toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
4069                                                 if [[ -n $toolkit ]];then
4070                                                         version="$version (Gtk $toolkit)"
4071                                                 fi
4072                                         fi
4073                                         desktop_environment="Xfce"
4074                                 elif [[ -n $( grep -is 'BLACKBOX_PID' <<< "$xprop_root" ) ]];then
4075                                         if [[ -n $( grep -is 'fluxbox' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4076                                                 version=$( get_de_app_version 'fluxbox' '^fluxbox' '2' )
4077                                                 desktop_environment='Fluxbox'
4078                                         else
4079                                                 desktop_environment='Blackbox'
4080                                         fi
4081                                 elif [[ -n $( grep -is 'OPENBOX_PID' <<< "$xprop_root" ) ]];then
4082                                         # note: openbox-lxde --version may be present, but returns openbox data
4083                                         version=$( get_de_app_version 'openbox' '^openbox' '2' )
4084                                         if [[ $XDG_CURRENT_DESKTOP == 'LXDE' || \
4085                                                         -n $( grep -is 'lxde' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4086                                                 if [[ -n $version ]];then
4087                                                         version="(Openbox $version)"
4088                                                 fi
4089                                                 desktop_environment='LXDE'
4090                                         elif [[ -n $( grep -is 'razor-desktop' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4091                                                 if [[ -n $version ]];then
4092                                                         version="(Openbox $version)"
4093                                                 fi
4094                                                 desktop_environment='Razor-QT'
4095                                         else
4096                                                 desktop_environment='Openbox'
4097                                         fi
4098                                 elif [[ -n $( grep -is 'ICEWM' <<< "$xprop_root" ) ]];then
4099                                         version=$( get_de_app_version 'icewm' '^icewm' '2' )
4100                                         desktop_environment='IceWM'
4101                                 elif [[ -n $( grep -is 'ENLIGHTENMENT' <<< "$xprop_root" ) ]];then
4102                                         # no -v or --version but version is in xprop -root
4103                                         # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898"
4104                                         version=$( grep -is 'ENLIGHTENMENT_VERSION' <<< "$xprop_root" | cut -d '"' -f 2 | gawk '{print $2}' )
4105                                         desktop_environment='Enlightenment'
4106                                 elif [[ -n $( grep -is '^I3_' <<< "$xprop_root" ) ]];then
4107                                         version=$( get_de_app_version 'i3' '^i3' '3' )
4108                                         desktop_environment='i3'
4109                                 elif [[ -n $( grep -is 'WINDOWMAKER' <<< "$xprop_root" ) ]];then
4110                                         version=$( get_de_app_version 'wmaker' '^Window[[:space:]]*Maker' 'NF' )
4111                                         if [[ -n $version ]];then
4112                                                 version="$version "
4113                                         fi
4114                                         desktop_environment="WindowMaker"
4115                                 elif [[ -n $( grep -is '^_WM2' <<< "$xprop_root" ) ]];then
4116                                         # note; there isn't actually a wm2 version available but error handling should cover it and return null
4117                                         # maybe one day they will add it?
4118                                         version=$( get_de_app_version 'wm2' '^wm2' 'NF' )
4119                                         # not certain will always have version, so keep output right if not
4120                                         if [[ -n $version ]];then
4121                                                 version="$version "
4122                                         fi
4123                                         desktop_environment="WM2"
4124                                 elif [[ -n $( grep -is 'herbstluftwm' <<< "$xprop_root" ) ]];then
4125                                         version=$( get_de_app_version 'herbstluftwm' '^herbstluftwm' 'NF' )
4126                                         if [[ -n $version ]];then
4127                                                 version="$version "
4128                                         fi
4129                                         desktop_environment="herbstluftwm"
4130                                 fi
4131                         fi
4132                         # a few manual hacks for things that don't id with xprop, these are just good guesses
4133                         # note that gawk is going to exit after first occurance of search string, so no need for extra
4134                         if [[ -z $desktop_environment ]];then
4135                                 if [[ -n $( grep -is 'fvwm-crystal'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4136                                         version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
4137                                         desktop_environment='FVWM-Crystal'
4138                                 elif [[ -n $( grep -is 'fvwm'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4139                                         version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
4140                                         desktop_environment='FVWM'
4141                                 elif [[ -n $( grep -is 'pekwm'  <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4142                                         version=$( get_de_app_version 'pekwm' '^pekwm' '3' )
4143                                         desktop_environment='pekwm'
4144                                 elif [[ -n $( grep -is 'awesome' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4145                                         version=$( get_de_app_version 'awesome' '^awesome' '2' )
4146                                         desktop_environment='Awesome'
4147                                 elif [[ -n $( grep -is 'scrotwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4148                                         version=$( get_de_app_version 'scrotwm' '^welcome.*scrotwm' '4' )
4149                                         desktop_environment='Scrotwm' # no --version for this one
4150                                 elif [[ -n $( grep -is 'spectrwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4151                                         version=$( get_de_app_version 'spectrwm' '^spectrwm.*welcome.*spectrwm' '5' )
4152                                         desktop_environment='Spectrwm' # no --version for this one
4153                                 elif [[ -n $( grep -Eis '([[:space:]]|/)twm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4154                                         desktop_environment='Twm' # no --version for this one
4155                                 elif [[ -n $( grep -Eis '([[:space:]]|/)dwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4156                                         version=$( get_de_app_version 'dwm' '^dwm' '1' )
4157                                         desktop_environment='dwm'
4158                                 elif [[ -n $( grep -is 'wmii2' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4159                                         version=$( get_de_app_version 'wmii2' '^wmii2' '1' )
4160                                         desktop_environment='wmii2'
4161                                 # note: in debian at least, wmii is actuall wmii3
4162                                 elif [[ -n $( grep -is 'wmii' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4163                                         version=$( get_de_app_version 'wmii' '^wmii' '1' )
4164                                         desktop_environment='wmii'
4165                                 elif [[ -n $( grep -Eis '([[:space:]]|/)jwm' <<< "$Ps_aux_Data" | grep -v 'grep' ) ]];then
4166                                         version=$( get_de_app_version 'jwm' '^jwm' '2' )
4167                                         desktop_environment='JWM'
4168                                 fi
4169                         fi
4170                 fi
4171         fi
4172         if [[ -n $version ]];then
4173                 version=" $version"
4174         fi
4175         echo "$desktop_environment${version}"
4176         eval $LOGFE
4177 }
4178
4179 # note: gawk doesn't support white spaces in search string, gave errors, so use [[:space:]] instead
4180 # args: $1 - desktop/app command for --version; $2 - search string; $3 - gawk print number
4181 get_de_app_version()
4182 {
4183         local version_data='' version='' get_version='--version' 
4184         
4185         # mate-about -v = MATE Desktop Environment 1.4.0
4186         case $1 in
4187                 dwm|jwm|mate-about|wmii|wmii2)
4188                         get_version='-v'
4189                         ;;
4190                 epoch)
4191                         get_version='version'
4192                         ;;
4193         esac
4194         
4195         case $1 in
4196                 # note, some wm/apps send version info to stderr instead of stdout
4197                 dwm|ksh|scrotwm|spectrwm)
4198                         version_data="$( $1 $get_version 2>&1 )"
4199                         ;;
4200                 csh)
4201                         version_data="$( tcsh $get_version 2>/dev/null )"
4202                         ;;
4203                 # quick debian/buntu hack until I find a universal way to get version for these
4204                 dash)
4205                         if [[ -n $( type -p dpkg ) ]];then
4206                                 version_data="$( dpkg -l $1 2>/dev/null )"
4207                         fi
4208                         ;;
4209                 *)
4210                         version_data="$( $1 $get_version 2>/dev/null )"
4211                         ;;
4212         esac
4213         
4214         if [[ -n $version_data ]];then
4215                 version=$( gawk '
4216                 BEGIN {
4217                         IGNORECASE=1
4218                 }
4219                 /'$2'/ {
4220                         # sample: dwm-5.8.2, Â©.. etc, why no space? who knows. Also get rid of v in number string
4221                         # xfce, and other, output has , in it, so dump all commas and parentheses
4222                         gsub(/(,|dwm-|wmii2-|wmii-|v|V|\(|\))/, "",$'$3') 
4223                         print $'$3'
4224                         exit # quit after first match prints
4225                 }' <<< "$version_data" )
4226         fi
4227         echo $version
4228 }
4229
4230 get_desktop_extra_data()
4231 {
4232         eval $LOGFS
4233         local de_data=$( ps -A | gawk '
4234         BEGIN {
4235                 IGNORECASE=1
4236                 desktops=""
4237                 separator=""
4238         }
4239         /(gnome-shell|gnome-panel|kicker|lxpanel|mate-panel|plasma-desktop|xfce4-panel)$/ {
4240                 # only one entry per type, can be multiple
4241                 if ( desktops !~ $NF ) {
4242                         desktops = desktops separator $NF
4243                         separator = ","
4244                 }
4245         }
4246         END {
4247                 print desktops
4248         }
4249         ' )
4250         echo $de_data
4251         
4252         eval $LOGFE
4253 }
4254
4255 get_de_gtk_data()
4256 {
4257         eval $LOGFS
4258         
4259         local toolkit=''
4260         
4261         # this is a hack, and has to be changed with every toolkit version change, and only dev systems
4262         # have this installed, but it's a cross distro command so let's test it first
4263         if [[ -n $( type -p pkg-config ) ]];then
4264                 toolkit=$( pkg-config --modversion gtk+-4.0 2>/dev/null )
4265                 # note: opensuse gets null output here, we need the command to get version and output sample
4266                 if [[ -z $toolkit ]];then
4267                         toolkit=$( pkg-config --modversion gtk+-3.0 2>/dev/null )
4268                 fi
4269                 if [[ -z $toolkit ]];then
4270                         toolkit=$( pkg-config --modversion gtk+-2.0 2>/dev/null )
4271                 fi
4272         fi
4273         # now let's go to more specific version tests, this will never cover everything and that's fine.
4274         if [[ -z $toolkit ]];then
4275                 # we'll try some known package managers next. dpkg will handle a lot of distros 
4276                 # this is the most likely order as of: 2014-01-13. Not going to try to support all package managers
4277                 # too much work, just the very biggest ones.
4278                 if [[ -n $( type -p dpkg ) ]];then
4279                         toolkit=$( dpkg -s libgtk-3-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4280                         if [[ -z $toolkit ]];then
4281                                 toolkit=$( dpkg -s libgtk2.0-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4282                         fi
4283                         # just guessing on gkt 4 package name
4284                         if [[ -z $toolkit ]];then
4285                                 toolkit=$( dpkg -s libgtk-4-0 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4286                         fi
4287                 elif [[ -n $( type -p pacman ) ]];then
4288                         toolkit=$(  pacman -Qi gtk3 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4289                         if [[ -z $toolkit ]];then
4290                                 toolkit=$( pacman -Qi gtk2 2>/dev/null | gawk -F ':' '/^Version/ {print $2}' )
4291                         fi
4292                 fi
4293         fi
4294         echo $toolkit
4295         
4296         eval $LOGFE
4297 }
4298
4299 # see which dm has started if any
4300 get_display_manager()
4301 {
4302         eval $LOGFS
4303         # ldm - LTSP display manager
4304         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' 
4305         local dm_id='' dm='' separator=''
4306         # note we don't need to filter grep if we do it this way
4307         local x_is_running=$( grep '/usr.*/X' <<< "$Ps_aux_Data" | grep -iv '/Xprt' )
4308
4309         for dm_id in $dm_id_list
4310         do
4311                 if [[ -e /var/run/$dm_id || -e /run/$dm_id ]];then
4312                         # just on the off chance that two dms are running, good info to have in that case, if possible
4313                         dm=$dm$separator$( basename $dm_id | cut -d '.' -f 1 )
4314                         separator=','
4315                 fi
4316         done
4317         # might add this in, but the rate of new dm's makes it more likely it's an unknown dm, so
4318         # we'll keep output to N/A
4319         if [[ -n $x_is_running && -z $dm ]];then
4320                 if [[ -n $( grep 'startx$' <<< "$Ps_aux_Data" ) ]];then
4321                         dm='(startx)'
4322                 fi
4323         fi
4324         echo $dm
4325
4326         log_function_data "display manager: $dm"
4327
4328         eval $LOGFE
4329 }
4330
4331 # for more on distro id, please reference this python thread: http://bugs.python.org/issue1322
4332 ## return distro name/id if found
4333 get_distro_data()
4334 {
4335         eval $LOGFS
4336         local i='' j='' distro='' distro_file='' a_distro_glob='' temp_array=''
4337         
4338         # may need modification if archbsd / debian can be id'ed with /etc files
4339         if [[ -n $BSD_TYPE ]];then
4340                 distro=$( uname -sr )
4341                 echo "$distro"
4342                 log_function_data "distro: $distro"
4343                 eval $LOGFE
4344                 return 0
4345         fi
4346
4347         # get the wild carded array of release/version /etc files if present
4348         shopt -s nullglob
4349         cd /etc
4350         # note: always exceptions, so wild card after release/version: /etc/lsb-release-crunchbang
4351         # wait to handle since crunchbang file is one of the few in the world that uses this method
4352         a_distro_glob=(*[-_]{release,version})
4353         cd "$OLDPWD"
4354         shopt -u nullglob
4355         
4356         temp_array=${a_distro_glob[@]}
4357         log_function_data "A_GLX_DATA: $temp_array"
4358
4359         if [[ ${#a_distro_glob[@]} -eq 1 ]];then
4360                 distro_file="${a_distro_glob}"
4361         # use the file if it's in the known good lists
4362         elif [[ ${#a_distro_glob[@]} -gt 1 ]];then
4363                 for i in $DISTROS_DERIVED $DISTROS_PRIMARY
4364                 do
4365                         # Only echo works with ${var[@]}, not print_screen_output() or script_debugger()
4366                         # This is a known bug, search for the word "strange" inside comments
4367                         # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'"
4368                         if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then
4369                                 # Now lets see if the distro file is in the known-good working-lsb-list
4370                                 # if so, use lsb-release, if not, then just use the found file
4371                                 # this is for only those distro's with self named release/version files
4372                                 # because Mint does not use such, it must be done as below 
4373                                 ## this if statement requires the spaces and * as it is, else it won't work
4374                                 ##
4375                                 if [[ " $DISTROS_LSB_GOOD " == *" ${i} "* ]] && [[ $B_LSB_FILE == 'true' ]];then
4376                                         distro_file='lsb-release'
4377                                 elif [[ " $DISTROS_OS_RELEASE_GOOD " == *" ${i} "* ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
4378                                         distro_file='os-release'
4379                                 else
4380                                         distro_file="${i}"
4381                                 fi
4382                                 break
4383                         fi
4384                 done
4385         fi
4386         log_function_data "distro_file: $distro_file"
4387         # first test for the legacy antiX distro id file
4388         if [[ -e /etc/antiX ]];then
4389                 distro="$( grep -Eoi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )"
4390         # this handles case where only one release/version file was found, and it's lsb-release. This would
4391         # never apply for ubuntu or debian, which will filter down to the following conditions. In general
4392         # if there's a specific distro release file available, that's to be preferred, but this is a good backup.
4393         elif [[ -n $distro_file && $B_LSB_FILE == 'true' && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then
4394                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4395         elif [[ $distro_file == 'lsb-release' ]];then
4396                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4397         elif [[ $distro_file == 'os-release' ]];then
4398                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
4399         # then if the distro id file was found and it's not in the exluded primary distro file list, read it
4400         elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then
4401                 # new opensuse uses os-release, but older ones may have a similar syntax, so just use the first line
4402                 if [[ $distro_file == 'SuSE-release' ]];then
4403                         # leaving off extra data since all new suse have it, in os-release, this file has line breaks, like os-release
4404                         # but in case we  want it, it's: CODENAME = Mantis  | VERSION = 12.2 
4405                         # for now, just take first occurance, which should be the first line, which does not use a variable type format
4406                         distro=$( grep -i -m 1 'suse' /etc/$distro_file )
4407                 else
4408                         distro=$( remove_erroneous_chars "/etc/$distro_file" )
4409                 fi
4410         # otherwise try  the default debian/ubuntu /etc/issue file
4411         elif [[ -f /etc/issue ]];then
4412                 # lsb gives more manageable and accurate output than issue, but mint should use issue for now
4413                 # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]]
4414                 if [[ $B_LSB_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
4415                         distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4416                 else
4417                         distro=$( gawk '
4418                         BEGIN {
4419                                 RS=""
4420                         }
4421                         {
4422                                 gsub(/\\[a-z]/, "")
4423                                 gsub(/,/, " ")
4424                                 gsub(/^ +| +$/, "")
4425                                 gsub(/ [ \t]+/, " ")
4426                                 print
4427                         }' /etc/issue )
4428                         
4429                         # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted
4430                         # only older arch installs that have not been updated should have this fallback required, new ones use
4431                         # os-release
4432                         if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then
4433                                 distro='Arch Linux'
4434                         fi
4435                 fi
4436         fi
4437         
4438         if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then
4439                 distro="${RED}/etc/${distro_file} corrupted, use -% to override${NORMAL}"
4440         fi
4441         ## note: would like to actually understand the method even if it's not used
4442         # : ${distro:=Unknown distro o_O}
4443         ## test for /etc/lsb-release as a backup in case of failure, in cases where > one version/release file
4444         ## were found but the above resulted in null distro value
4445         if [[ -z $distro ]] && [[ $B_LSB_FILE == 'true' ]];then
4446                 distro=$( get_distro_lsb_os_release_data 'lsb-file' )
4447         fi
4448         if [[ -z $distro ]] && [[ $B_OS_RELEASE_FILE == 'true' ]];then
4449                 distro=$( get_distro_lsb_os_release_data 'os-release-file' )
4450         fi
4451         # now some final null tries
4452         if [[ -z $distro ]];then
4453                 # if the file was null but present, which can happen in some cases, then use the file name itself to 
4454                 # set the distro value. Why say unknown if we have a pretty good idea, after all?
4455                 if [[ -n $distro_file ]] && [[ " $DISTROS_DERIVED $DISTROS_PRIMARY " == *" $distro_file "* ]];then
4456                         distro=$( sed $SED_RX -e 's/[-_]//' -e 's/(release|version)//' <<< $distro_file | sed $SED_RX 's/^([a-z])/\u\1/' )
4457                 fi
4458                 ## finally, if all else has failed, give up
4459                 if [[ -z $distro ]];then
4460                         distro='unknown'
4461                 fi
4462         fi
4463         # final step cleanup of unwanted information
4464         # opensuse has the x86 etc type string in names, not needed as redundant since -S already shows that
4465         distro=$( gawk '
4466         BEGIN {
4467                 IGNORECASE=1
4468         }
4469         {
4470                 sub(/ *\(*(x86_64|i486|i586|i686|686|586|486)\)*/, "", $0)
4471                 print $0
4472         }' <<< $distro )
4473         echo "$distro"
4474         log_function_data "distro: $distro"
4475         eval $LOGFE
4476 }
4477
4478 # args: $1 - lsb-file/lsb-app/os-release-file
4479 get_distro_lsb_os_release_data()
4480 {
4481         eval $LOGFS
4482         local distro=''
4483         
4484         case $1 in
4485                 lsb-file)
4486                         if [[ $B_LSB_FILE == 'true' ]];then
4487                                 distro=$( gawk -F '=' '
4488                                 BEGIN {
4489                                         IGNORECASE=1
4490                                 }
4491                                 # clean out unwanted characters
4492                                 { 
4493                                         gsub(/\\|\"|[:\47]/,"", $0 )
4494                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4495                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4496                                 }
4497                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
4498                                 /^DISTRIB_ID/ {
4499                                         # this is needed because grep for "arch" is too loose to be safe
4500                                         if ( $2 == "arch" ) {
4501                                                 distroId = "Arch Linux"
4502                                         }
4503                                         else if ( $2 != "n/a" ) {
4504                                                 distroId = $2 " "
4505                                         }
4506                                 }
4507                                 /^DISTRIB_RELEASE/ {
4508                                         if ( $2 != "n/a" ) {
4509                                                 distroRelease = $2 " "
4510                                         }
4511                                 }
4512                                 /^DISTRIB_CODENAME/ {
4513                                         if ( $2 != "n/a" ) {
4514                                                 distroCodename = $2 " "
4515                                         }
4516                                 }
4517                                 # sometimes some distros cannot do their lsb-release files correctly, so here is
4518                                 # one last chance to get it right.
4519                                 /^DISTRIB_DESCRIPTION/ {
4520                                         if ( $2 != "n/a" ) {
4521                                                 distroDescription = $2
4522                                         }
4523                                 }
4524                                 END {
4525                                         fullString=""
4526                                         if ( distroId == "" && distroRelease == "" && distroCodename == "" && distroDescription != "" ){
4527                                                 fullString = distroDescription
4528                                         }
4529                                         else {
4530                                                 fullString = distroId distroRelease distroCodename
4531                                         }
4532                                         print fullString
4533                                 }
4534                                 ' $FILE_LSB_RELEASE )
4535                                 log_function_data 'cat' "$FILE_LSB_RELEASE"
4536                         fi
4537                         ;;
4538                 lsb-app)
4539                         # this is HORRIBLY slow, not using
4540                         if [[  -n $( type -p lsb_release ) ]];then
4541                                 distro=$( echo "$( lsb_release -irc )" | gawk -F ':' '
4542                                 BEGIN { 
4543                                         IGNORECASE=1 
4544                                 }
4545                                 # clean out unwanted characters
4546                                 { 
4547                                         gsub(/\\|\"|[:\47]/,"", $0 )
4548                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4549                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4550                                 }
4551                                 /^Distributor ID/ {
4552                                         distroId = $2
4553                                 }
4554                                 /^Release/ {
4555                                         distroRelease = $2
4556                                 }
4557                                 /^Codename/ {
4558                                         distroCodename = $2
4559                                 }
4560                                 END {
4561                                         print distroId " " distroRelease " (" distroCodename ")"
4562                                 }' )
4563                         fi
4564                         ;;
4565                 os-release-file)
4566                         if [[ $B_OS_RELEASE_FILE == 'true' ]];then
4567                                 distro=$( gawk -F '=' '
4568                                 BEGIN {
4569                                         IGNORECASE=1
4570                                         prettyName=""
4571                                         regularName=""
4572                                         versionName=""
4573                                         versionId=""
4574                                         distroName=""
4575                                 }
4576                                 # clean out unwanted characters
4577                                 { 
4578                                         gsub(/\\|\"|[:\47]/,"", $0 )
4579                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2 )
4580                                         gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1 )
4581                                 }
4582                                 # note: adding the spacing directly to variable to make sure distro output is null if not found
4583                                 /^PRETTY_NAME/ {
4584                                         if ( $2 != "n/a" ) {
4585                                                 prettyName = $2
4586                                         }
4587                                 }
4588                                 /^NAME/ {
4589                                         if ( $2 != "n/a" ) {
4590                                                 regularName = $2
4591                                         }
4592                                 }
4593                                 /^VERSION/ {
4594                                         if ( $2 != "n/a" && $1 == "VERSION" ) {
4595                                                 versionName = $2
4596                                         }
4597                                         else if ( $2 != "n/a" && $1 == "VERSION_ID" ) {
4598                                                 versionId = $2
4599                                         }
4600                                 }
4601                                 END {
4602                                         if ( prettyName != "" ) {
4603                                                 distroName = prettyName
4604                                         }
4605                                         else if ( regularName != "" ) {
4606                                                 distroName = regularName
4607                                                 if ( versionName != "" ) {
4608                                                         distroName = distroName " " versionName
4609                                                 }
4610                                                 else if ( versionId != "" ) {
4611                                                         distroName = distroName " " versionId
4612                                                 }
4613                                                 
4614                                         }
4615                                         print distroName
4616                                 }
4617                                 ' $FILE_OS_RELEASE )
4618                                 log_function_data 'cat' "$FILE_OS_RELEASE"
4619                         fi
4620                         ;;
4621         esac
4622         echo $distro
4623         log_function_data "distro: $distro"
4624         eval $LOGFE
4625 }
4626
4627 get_dmidecode_data()
4628 {
4629         eval $LOGFS
4630         
4631         local dmidecodePath=''
4632
4633         if [[ $B_DMIDECODE_SET != 'true' ]];then
4634                 dmidecodePath=$( type -p dmidecode 2>/dev/null )
4635                 if [[ -n $dmidecodePath ]];then
4636                         # note stripping out these lines: Handle 0x0016, DMI type 17, 27 bytes
4637                         # but NOT deleting them, in case the dmidecode data is missing empty lines which will be
4638                         # used to separate results. Then we remove the doubled empty lines to keep it clean and
4639                         # strip out all the stuff we don't want to see in the results.
4640                         DMIDECODE_DATA="$( $dmidecodePath 2>/dev/null \
4641                         | gawk -F ':' '
4642                         BEGIN {
4643                                 IGNORECASE=1
4644                                 cutExtraTab="false"
4645                                 twoData=""
4646                                 oneData=""
4647                         }
4648                         {
4649                                 # no idea why, but freebsd gawk does not do this right
4650                                 oneData=$1
4651                                 twoData=$2
4652                                 if ( twoData != "" ) {
4653                                         twoHolder="true"
4654                                 }
4655                                 else {
4656                                         twoHolder="false"
4657                                 }
4658                                 if ( $0 ~ /^\tDMI type/ ) {
4659                                         sub(/^\tDMI type.*/, "", $0)
4660                                         cutExtraTab="true"
4661                                 }
4662                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", twoData)
4663                                 gsub(/,/, " ", $0)
4664                                 # clean out Handle line
4665                                 sub(/^Handle.*/,"", $0)
4666                                 sub(/^[[:space:]]*Inactive.*/,"",$0)
4667                                 # yes, there is a typo in a user data set, unknow
4668                                 # Base Board Version|Base Board Serial Number
4669                                 # Chassis Manufacturer|Chassis Version|Chassis Serial Number
4670                                 # System manufacturer|System Product Name|System Version
4671                                 # To Be Filled By O.E.M.
4672                                 # strip out starting white space so that the following stuff will clear properly
4673                                 sub(/^[[:space:]]+/, "", twoData)
4674                                 sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", twoData) 
4675                                 gsub(/bios|acpi/, "", twoData)
4676                                 sub(/http:\/\/www.abit.com.tw\//, "Abit", twoData)
4677                                 
4678                                 # for double indented values replace with ~ so later can test for it, we are trusting that
4679                                 # indentation will be tabbed in this case
4680                                 # special case, dmidecode 2.2 has an extra tab and a DMI type line
4681                                 if ( cutExtraTab == "true" ) {
4682                                         sub(/^\t\t\t+/, "~", oneData)
4683                                 }
4684                                 else {
4685                                         sub(/^\t\t+/, "~", oneData)
4686                                 }
4687                                 
4688                                 gsub(/^[[:space:]]+|[[:space:]]+$/, "", twoData)
4689                                 gsub(/^[[:space:]]+|[[:space:]]+$/, "", oneData)
4690                                 gsub(/ [ \t]+/, " ", twoData)
4691                                 # reconstructing the line for processing so gawk can use -F : again
4692                                 if ( oneData != "" && twoHolder == "true" ) {
4693                                         print oneData ":" twoData
4694                                 }
4695                                 else {
4696                                         print $0
4697                                 }
4698                         }' \
4699                         | sed '/^$/{
4700 N
4701 /^\n$/D
4702 }' \
4703                         )"
4704                 fi
4705                 B_DMIDECODE_SET='true'
4706                 log_function_data "DMIDECODE_DATA: $DMIDECODE_DATA"
4707         fi
4708
4709         eval $LOGFE
4710 }
4711 # get_dmidecode_data;echo "$DMIDECODE_DATA";exit
4712
4713 # BSD only
4714 get_dmesg_boot_data()
4715 {
4716         eval $LOGFS
4717         
4718         local dmsg_boot_data=''
4719         
4720         if [[ $B_DMESG_BOOT_FILE == 'true' ]];then
4721                 # replace all indented items with ~ so we can id them easily while processing
4722                 dmsg_boot_data="$( cat $FILE_DMESG_BOOT | sed $SED_RX 's/"//g' )"
4723         fi
4724         echo "$dmsg_boot_data"
4725         # log_function_data "$dmsg_boot_data"
4726         eval $LOGFE
4727 }
4728
4729 get_gcc_kernel_version()
4730 {
4731         # note that we use gawk to get the last part because beta, alpha, git versions can be non-numeric
4732         local gccVersion=''
4733         
4734         if [[ -e /proc/version ]];then
4735                 gccVersion=$( grep -Eio 'gcc[[:space:]]*version[[:space:]]*([^ \t]*)' /proc/version 2>/dev/null | gawk '{print $3}' )
4736         fi
4737         echo $gccVersion
4738 }
4739
4740 get_gcc_system_version()
4741 {
4742         eval $LOGFS
4743         local separator='' gcc_installed='' gcc_list='' gcc_others='' temp_array=''
4744         local gcc_version=$( 
4745         gcc --version 2>/dev/null | sed $SED_RX 's/\([^\)]*\)//g' | gawk '
4746         BEGIN {
4747                 IGNORECASE=1
4748         }
4749         /^gcc/ {
4750                 print $2
4751                 exit
4752         }'      )
4753
4754         # can't use xargs -L basename because not all systems support thats
4755         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
4756                 gcc_others=$( ls /usr/bin/gcc-* 2>/dev/null )
4757                 if [[ -n $gcc_others ]];then
4758                         for item in $gcc_others
4759                         do
4760                                 gcc_installed=$( basename $item | gawk -F '-' '
4761                                 $2 ~ /^[0-9\.]+$/ {
4762                                         print $2
4763                                 }' )
4764                                 if [[ -n $gcc_installed && -z $( grep "^$gcc_installed" <<< $gcc_version ) ]];then
4765                                         gcc_list=$gcc_list$separator$gcc_installed
4766                                         separator=','
4767                                 fi
4768                         done
4769                 fi
4770         fi
4771         if [[ -n $gcc_version ]];then
4772                 A_GCC_VERSIONS=( "$gcc_version" $gcc_list )
4773         fi
4774         temp_array=${A_GCC_VERSIONS[@]}
4775         log_function_data "A_GCC_VERSIONS: $temp_array"
4776         eval $LOGFE
4777 }
4778 get_gpu_temp_data()
4779 {
4780         local gpu_temp='' gpu_fan='' screens='' screen_nu='' gpu_temp_looper=''
4781
4782         # we'll try for nvidia/ati, then add if more are shown
4783         if [[ -n $( type -p nvidia-settings ) ]];then
4784                 # first get the number of screens
4785                 screens=$( nvidia-settings -q screens | gawk '
4786                 /:[0-9]\.[0-9]/ {
4787                         screens=screens gensub(/(.*)(:[0-9]\.[0-9])(.*)/, "\\2", "1", $0) " "
4788                 }
4789                 END {
4790                         print screens
4791                 }
4792                 ' )
4793                 # now we'll get the gpu temp for each screen discovered. The print out function
4794                 # will handle removing screen data for single gpu systems
4795                 for screen_nu in $screens
4796                 do
4797                         gpu_temp_looper=$( nvidia-settings -c $screen_nu -q GPUCoreTemp | gawk -F ': ' '
4798                         BEGIN {
4799                                 IGNORECASE=1
4800                                 gpuTemp=""
4801                                 gpuTempWorking=""
4802                         }
4803                         /Attribute (.*)[0-9]+\.$/ {
4804                                 gsub(/\./, "", $2)
4805                                 if ( $2 ~ /^[0-9]+$/ ) {
4806                                         gpuTemp=gpuTemp $2 "C "
4807                                 }
4808                         }
4809                         END {
4810                                 print gpuTemp
4811                         }'      )
4812                         screen_nu=$( cut -d ':' -f 2 <<< $screen_nu )
4813                         gpu_temp="$gpu_temp$screen_nu:$gpu_temp_looper "
4814                 done
4815         elif [[ -n $( type -p aticonfig ) ]];then
4816 #               gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' '
4817                 gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' '
4818                 BEGIN {
4819                         IGNORECASE=1
4820                         gpuTemp=""
4821                         gpuTempWorking=""
4822                 }
4823                 /Sensor (.*)[0-9\.]+ / {
4824                         gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2)
4825                         if ( gpuTempWorking ~ /^[0-9\.]+$/ ) {
4826                                 gpuTemp=gpuTemp gpuTempWorking "C "
4827                         }
4828                 }
4829                 END {
4830                         print gpuTemp
4831                 }'      )
4832         # this handles some newer cases of free driver temp readouts, will require modifications as
4833         # more user data appears.
4834         elif [[ -n $Sensors_Data ]];then
4835                 gpu_temp=$( 
4836                 gawk '
4837                 BEGIN {
4838                         IGNORECASE=1
4839                         gpuTemp=""
4840                         separator=""
4841                 }
4842                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
4843                         while ( getline && !/^$/  ) {
4844                                 if ( /^temp/ ) {
4845                                         sub(/^[[:alnum:]]*.*:/, "", $0 ) # clear out everything to the :
4846                                         gsub(/[\+ \t°]/, "", $1) # Â° is a special case, like a space for gawk
4847                                         gpuTemp=gpuTemp separator $1
4848                                         separator=","
4849                                 }       
4850                         }
4851                 }
4852                 END {
4853                         print gpuTemp
4854                 }' <<< "$Sensors_Data" )
4855         fi
4856         
4857         if [[ -n $gpu_temp ]];then
4858                 echo $gpu_temp
4859         fi
4860 }
4861
4862 ## for possible future data, not currently used
4863 get_graphics_agp_data()
4864 {
4865         eval $LOGFS
4866         local agp_module=''
4867
4868         if [[ $B_MODULES_FILE == 'true' ]];then
4869                 ## not used currently
4870                 agp_module=$( gawk '
4871                 /agp/ && !/agpgart/ && $3 > 0 {
4872                         print(gensub(/(.*)_agp.*/,"\\1","g",$1))
4873                 }' $FILE_MODULES )
4874                 log_function_data 'cat' "$FILE_MODULES"
4875         fi
4876         log_function_data "agp_module: $agp_module"
4877         eval $LOGFE
4878 }
4879
4880 ## create array of gfx cards installed on system
4881 get_graphics_card_data()
4882 {
4883         eval $LOGFS
4884         local i='' temp_array=''
4885
4886         IFS=$'\n'
4887         A_GRAPHICS_CARD_DATA=( $( gawk -F': ' '
4888         BEGIN {
4889                 IGNORECASE=1
4890                 busId=""
4891         }
4892         /vga compatible controller/ {
4893                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF)
4894                 gsub(/,/, " ", $NF)
4895                 gsub(/^ +| +$/, "", $NF)
4896                 gsub(/ [ \t]+/, " ", $NF)
4897                 busId=gensub(/^([0-9a-f:\.]+) (.+)$/,"\\1","",$1)
4898                 print $NF "," busId
4899         }' <<< "$Lspci_v_Data" ) )
4900         IFS="$ORIGINAL_IFS"
4901 #       for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
4902 #       do
4903 #               A_GRAPHICS_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GRAPHICS_CARD_DATA[i]}" )
4904 #       done
4905
4906         # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory..
4907         # 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]"
4908         temp_array=${A_GRAPHICS_CARD_DATA[@]}
4909         log_function_data "A_GRAPHICS_CARD_DATA: $temp_array"
4910         eval $LOGFE
4911 }
4912
4913 get_graphics_driver()
4914 {
4915         eval $LOGFS
4916         
4917         # list is from sgfxi plus non-free drivers
4918         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'
4919         local driver='' driver_string='' xorg_log_data='' status='' temp_array=''
4920
4921         if [[ $B_XORG_LOG == 'true' ]];then
4922                 A_GRAPHIC_DRIVERS=( $(
4923                 gawk '
4924                 BEGIN {
4925                         driver=""
4926                         bLoaded="false"
4927                         IGNORECASE=1
4928                 }
4929                 # note that in file names, driver is always lower case
4930                 /[[:space:]]Loading.*('"$driver_list"')_drv.so$/ {
4931                         driver=gensub(/.*[[:space:]]Loading.*('"$driver_list"')_drv.so/, "\\1", 1, $0 )
4932                         # we get all the actually loaded drivers first, we will use this to compare the
4933                         # failed/unloaded, which have not always actually been truly loaded
4934                         aDrivers[driver]="loaded" 
4935                 }
4936                 /Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/ {
4937                         driver=gensub(/(.*)Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/, "\\2", 1, $0 )
4938                         # we need to make sure that the driver has already been truly loaded, not just discussed
4939                         if ( driver in aDrivers ) {
4940                                 aDrivers[driver]="unloaded"
4941                         }
4942                 }
4943                 /Failed.*('"$driver_list"')_drv.so|Failed.*\"('"$driver_list"')\"/ {
4944                         driver=gensub(/(.*)Failed.*('"$driver_list"')_drv.so/, "\\2", 1, $0 )
4945                         if ( driver == $0 ) {
4946                                 driver=gensub(/(.*)Failed.*\"('"$driver_list"')\".*|fred/, "\\2", 1, $0 )
4947                         }
4948                         # we need to make sure that the driver has already been truly loaded, not just discussed
4949                         if ( driver != $0 && driver in aDrivers ) {
4950                                 aDrivers[driver]="failed"
4951                         }
4952                 }
4953                 # verify that the driver actually started the desktop, even with false failed messages which can occur
4954                 # this is the driver that is actually driving the display
4955                 /.*\([0-9]+\):[[:space:]]Depth.*framebuffer/ {
4956                         driver=gensub(/.*('"$driver_list"')\([0-9]+\):[[:space:]]Depth.*framebuffer.*/, "\\1", 1, $0 )
4957                         # we need to make sure that the driver has already been truly loaded, not just discussed, also
4958                         # set driver to lower case because sometimes it will show as RADEON or NVIDIA in the actual x start
4959                         driver=tolower(driver)
4960                         if ( driver != $0 && driver in aDrivers ) {
4961                                 aDrivers[driver]="loaded"
4962                         }
4963                 }
4964                 END {
4965                         for ( driver in aDrivers ) {
4966                                 print driver "," aDrivers[driver]
4967                         }
4968                 }' < $FILE_XORG_LOG ) )
4969         fi
4970         temp_array=${A_GRAPHIC_DRIVERS[@]}
4971         log_function_data "A_GRAPHIC_DRIVERS: $temp_array"
4972         
4973         eval $LOGFE
4974 }
4975
4976 ## create array of glx data
4977 get_graphics_glx_data()
4978 {
4979         eval $LOGFS
4980         local temp_array=''
4981         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
4982                 IFS=$'\n'
4983                 A_GLX_DATA=( $( glxinfo | gawk -F ': ' '
4984                 # note: function declarations go before BEGIN? It appears so, confirm.
4985                 # the real question here though is why this function is even here, seems
4986                 # just to be a complicated way to pack/print a variable, but maybe the
4987                 # original idea was to handle > 1 cases of detections I guess
4988                 function join( arr, sep ) {
4989                         s=""
4990                         i=flag=0
4991                         for ( i in arr ) {
4992                                 if ( flag++ ) {
4993                                         s = s sep
4994                                 }
4995                                 s = s i
4996                         }
4997                         return s
4998                 }
4999
5000                 BEGIN {
5001                         IGNORECASE=1
5002                 }
5003                 /opengl renderer/ {
5004                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
5005                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
5006                         gsub(/^ +| +$/, "", $2)
5007                         if ( $2 ~ /mesa/ ) {
5008                                 # Allow all mesas
5009 #                               if ( $2 ~ / r[3-9][0-9][0-9] / ) {
5010                                         a[$2]
5011                                         # this counter failed in one case, a bug, and is not needed now
5012 #                                       f++
5013 #                               }
5014                                 next
5015                         }
5016                         
5017                         $2 && a[$2]
5018                 }
5019                 # dropping all conditions from this test to just show full mesa information
5020                 # there is a user case where not f and mesa apply, atom mobo
5021                 # /opengl version/ && ( f || $2 !~ /mesa/ ) {
5022                 /opengl version/ {
5023                         # fglrx started appearing with this extra string, does not appear to communicate anything of value
5024                         sub(/Compatibility Profile Context/, "- CPC", $2 )
5025                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
5026                         gsub(/^ +| +$/, "", $2)
5027                         $2 && b[$2]
5028                 }
5029                 /direct rendering/ {
5030                         $2 && c[$2]
5031                 }
5032                 END {
5033                         printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) )
5034                 }' ) )
5035                 IFS="$ORIGINAL_IFS"
5036
5037                 # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
5038                 #    GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
5039         fi
5040         temp_array=${A_GLX_DATA[@]}
5041         log_function_data "A_GLX_DATA: $temp_array"
5042         eval $LOGFE
5043 }
5044
5045 ## return screen resolution / tty resolution
5046 get_graphics_res_data()
5047 {
5048         eval $LOGFS
5049         local screen_resolution='' xdpy_data='' screens_count=0 tty_session=''
5050
5051         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
5052                 # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in
5053                 # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0
5054                 xdpy_data="$( xdpyinfo )"
5055                 xdpy_count=$( grep -c 'dimensions' <<< "$xdpy_data" )
5056                 # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
5057                 # multiple screens from different video cards
5058                 if [[ $xdpy_count -eq 1 ]];then
5059                         screen_resolution=$( xrandr | gawk '
5060                         /\*/ {
5061                                 res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0)
5062                         }
5063                         END {
5064                                 for (n in res) {
5065                                         if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) {
5066                                                 line = line ? line ", " res[n] : res[n]
5067                                         }
5068                                 }
5069                                 if (line) {
5070                                         print(line)
5071                                 }
5072                         }' )
5073                 fi
5074                 if [[ -z $screen_resolution || $xdpy_count -gt 1 ]];then
5075                         screen_resolution=$( gawk '
5076                         BEGIN {
5077                                 IGNORECASE=1
5078                                 screens = ""
5079                                 separator = ""
5080                         }
5081                         /dimensions/ {
5082                                 screens = screens separator # first time, this is null, next, has comma last
5083                                 screens = screens $2 # then tack on the new value for nice comma list
5084                                 separator = ", "
5085                         }
5086                         END {
5087                                 print screens
5088                         }' <<< "$xdpy_data" )
5089                 fi
5090         else
5091                 if [[ $B_PROC_DIR == 'true' && -z $BSD_TYPE ]];then
5092                         screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{
5093                                 print $2"x"$1
5094                         }' )
5095                 # note: this works fine for all systems but keeping the above for now since
5096                 # the above is probably more accurate for linux systems.
5097                 else
5098                         if [[ $B_CONSOLE_IRC != 'true' ]];then
5099                                 screen_resolution=$( stty -a | gawk -F ';' '
5100                                         /^speed/ {
5101                                                 gsub(/[[:space:]]*(rows|columns)[[:space:]]*/,"",$0)
5102                                                 gsub(/[[:space:]]*/,"",$2)
5103                                                 gsub(/[[:space:]]*/,"",$3)
5104                                                 print $3"x"$2
5105                                         }' )
5106                         else
5107                                 if [[ -n $BSD_TYPE ]];then
5108                                         tty_session=$( get_tty_console_irc )
5109                                         # getting information for tty that owns the irc client
5110                                         screen_resolution="$( stty -f /dev/pts/$tty_session size | gawk '{print $2"x"$1}' )"
5111                                 fi
5112                         fi
5113                 fi
5114         fi
5115         echo "$screen_resolution"
5116         log_function_data "screen_resolution: $screen_resolution"
5117         eval $LOGFE
5118 }
5119
5120 ## create array of display server vendor/version data
5121 get_graphics_display_server_data()
5122 {
5123         eval $LOGFS
5124         local vendor='' version='' temp_array='' xdpy_info='' a_display_vendor_working=''
5125
5126         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
5127                 # X vendor and version detection.
5128                 # new method added since radeon and X.org and the disappearance of <X server name> version : ...etc
5129                 # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2
5130                 # A failover mechanism is in place. (if $version is empty, the release number is parsed instead)
5131                 # xdpy_info="$( xdpyinfo )"
5132                 IFS=","
5133                 a_display_vendor_working=( $( xdpyinfo | gawk -F': +' '
5134                 BEGIN {
5135                         IGNORECASE=1
5136                         vendorString=""
5137                         version=""
5138                         vendorRelease=""
5139                 }
5140                 /vendor string/ {
5141                         gsub(/the|inc|foundation|project|corporation/, "", $2)
5142                         gsub(/,/, " ", $2)
5143                         gsub(/^ +| +$/, "", $2)
5144                         gsub(/ [ \t]+/, " ", $2)
5145                         vendorString = $2
5146                 }
5147                 /version:/ {
5148                         version = $NF
5149                 }
5150                 /vendor release number/ {
5151                         gsub(/0+$/, "", $2)
5152                         gsub(/0+/, ".", $2)
5153                         vendorRelease = $2
5154                 }
5155                 END {
5156                         print vendorString "," version "," vendorRelease
5157                 }' ) )
5158                 vendor=${a_display_vendor_working[0]}
5159                 version=${a_display_vendor_working[1]}
5160
5161                 # this gives better output than the failure last case, which would only show:
5162                 # for example: X.org: 1.9 instead of: X.org: 1.9.0
5163                 if [[ -z $version ]];then
5164                         version=$( get_graphics_display_server_version )
5165                 fi
5166                 if [[ -z $version ]];then
5167                         version=${a_display_vendor_working[2]}
5168                 fi
5169                 
5170                 # some distros, like fedora, report themselves as the xorg vendor, so quick check
5171                 # here to make sure the vendor string includes Xorg in string
5172                 if [[ -z $( grep -E '(X|xorg|x\.org)' <<< $vendor ) ]];then
5173                         vendor="$vendor X.org"
5174                 fi
5175                 IFS="$ORIGINAL_IFS"
5176                 A_DISPLAY_SERVER_DATA[0]="$vendor"
5177                 A_DISPLAY_SERVER_DATA[1]="$version"
5178         else
5179                 version=$( get_graphics_display_server_version )
5180                 if [[ -n $version ]];then
5181                         vendor='X.org'
5182                         A_DISPLAY_SERVER_DATA[0]="$vendor"
5183                         A_DISPLAY_SERVER_DATA[1]="$version"
5184                 fi
5185         fi
5186         temp_array=${A_DISPLAY_SERVER_DATA[@]}
5187         log_function_data "A_DISPLAY_SERVER_DATA: $temp_array"
5188         eval $LOGFE
5189 }
5190
5191 # if other tests fail, try this one, this works for root, out of X also
5192 get_graphics_display_server_version()
5193 {
5194         eval $LOGFS
5195         local version='' x_data=''
5196         # note that some users can have /usr/bin/Xorg but not /usr/bin/X
5197         if [[ -n $( type -p X ) ]];then
5198                 # note: MUST be this syntax: X -version 2>&1
5199                 # otherwise X -version overrides everything and this comes out null.
5200                 # two knowns id strings: X.Org X Server 1.7.5 AND X Window System Version 1.7.5
5201                 #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }'
5202                 x_data="$( X -version 2>&1 )"
5203         elif [[ -n $( type -p Xorg ) ]];then
5204                 x_data="$( Xorg -version 2>&1)"
5205         fi
5206         if [[ -n $x_data ]];then
5207                 version=$( 
5208                 gawk '
5209                 BEGIN {
5210                         IGNORECASE=1
5211                 }
5212                 /^x.org x server/ {
5213                         print $4
5214                         exit
5215                 }
5216                 /^X Window System Version/ {
5217                         print $5
5218                         exit
5219                 }' <<< "$x_data" )
5220         fi
5221         echo $version
5222         log_function_data " version: $version"
5223         eval $LOGFE
5224 }
5225
5226 # this gets just the raw data, total space/percent used and disk/name/per disk capacity
5227 get_hdd_data_basic()
5228 {
5229         eval $LOGFS
5230         local hdd_used='' temp_array='' df_string=''
5231         local hdd_data='' df_test=''
5232         
5233         if [[ -z $BSD_TYPE ]];then
5234                 df_string='df -P -T --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
5235                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs
5236                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs'
5237         else
5238                 # default size is 512, so use -k for 1024
5239                 df_string='df -T -k'
5240                 # default size is 512, -H only for size in human readable format
5241                 # older bsds don't support -T, pain, so we'll use partial output there
5242                 df_test=$( df -H -T 2>/dev/null )
5243                 if [[ -n $df_test ]];then
5244                         df_string='df -k -T'
5245                 else
5246                         df_string='df -k'
5247                 fi
5248         fi
5249         hdd_data="$( eval $df_string )"
5250         log_function_data 'raw' "hdd_data:\n$hdd_data"
5251         hdd_used=$(     echo "$hdd_data" | gawk -v bsdType=$BSD_TYPE '
5252         BEGIN {
5253                 # this is used for specific cases where bind, or incorrect multiple mounts to same partitions,
5254                 # is present. The value is searched for an earlier appearance of that partition and if it is 
5255                 # present, the data is not added into the partition used size.
5256                 partitionsSet=""
5257                 # this handles a case where the same dev item is mounted twice to different points
5258                 devSet=""
5259                 devWorking=""
5260                 mountWorking=""
5261         }
5262         # using $1, not $2, because older bsd df do not have -T, filesystem type
5263         ( bsdType != "" ) && $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|filesystem|iso9660|linprocfs|procfs|squashfs|sysfs|tmpfs|type|unionfs)$/ {
5264                 # note use next, not getline or it does not work right
5265                 next 
5266         }
5267         # also handles odd dm-1 type, from lvm, and mdraid, and some other bsd partition syntax
5268         # note that linux 3.2.45-grsec-9th types kernels have this type of partition name: /dev/xvdc (no number, letter)
5269         /^\/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])/ {
5270                 # this handles the case where the first item is too long
5271                 # and makes df wrap output to next line, so here we advance
5272                 # it to the next line for that single case. Using df -P should
5273                 # make this unneeded but leave it in just in case
5274                 if ( NF < 6 && $0 !~ /.*%/ ) {
5275                         devSet = devSet "~" $1 "~"
5276                         getline
5277                 }
5278                 # if the first item caused a wrap, use one less than standard
5279                 # testing for the field with % in it, ie: 34%, then go down from there
5280                 # this also protects against cases where the mount point has a space in the
5281                 # file name, thus breaking going down from $NF directly.
5282                 # some bsds will also have only 6 items
5283                 if ( $5 ~ /.*%/ ) {
5284                         devWorking="~" $1 "~"
5285                         mountWorking="~" $6 "~"
5286                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
5287                                 used += $3
5288                         }
5289                         partitionsSet = partitionsSet mountWorking
5290                         # make sure to only include bsd real lines here, ie, short df output
5291                         if ( $1 ~ /^\/dev\// ) {
5292                                 devSet = devSet devWorking
5293                         }
5294                 }
5295                 # otherwise use standard
5296                 else if ( $6 ~ /.*%/ ) {
5297                         devWorking="~" $1 "~"
5298                         mountWorking="~" $7 "~"
5299                         if ( partitionsSet !~ mountWorking && devSet !~ devWorking ) {
5300                                 used += $4
5301                         }
5302                         partitionsSet = partitionsSet mountWorking
5303                         devSet = devSet devWorking
5304                 }
5305                 # and if this is not detected, give up, we need user data to debug
5306                 else {
5307                         next
5308                 }
5309         }
5310         END {
5311                 print used
5312         }' )
5313
5314         if [[ -z $hdd_used ]];then
5315                 hdd_used='na'
5316         fi
5317         log_function_data "hdd_used: $hdd_used"
5318         # create the initial array strings:
5319         # disk-dev, capacity, name, usb or not
5320         # final item is the total of the disk
5321         IFS=$'\n'
5322
5323         if [[ $B_PARTITIONS_FILE == 'true' ]];then
5324                 A_HDD_DATA=( $(
5325                 gawk -v hddused="$hdd_used" '
5326                 /[hsv]d[a-z]$/ {
5327                         driveSize = $(NF - 1)*1024/1000**3
5328                         gsub(/,/, " ", driveSize)
5329                         gsub(/^ +| +$/, "", driveSize)
5330                         printf( $NF",%.1fGB,,\n", driveSize )
5331                 }
5332                 # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
5333                 # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0  {
5334                 #       size += $3
5335                 # }
5336                 # special case from this data: 8     0  156290904 sda
5337                 # note: vm has 252/253/254 known starter, grsec has 202
5338                 $1 ~ /^(3|8|22|33|202|252|253|254)$/ && $NF ~ /[hsv]d[a-z]$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) {
5339                         size += $3
5340                 }
5341
5342                 END {
5343                         size = size*1024/1000**3                   # calculate size in GB size
5344                         workingUsed = hddused*1024/1000**3         # calculate workingUsed in GB used
5345                         # this handles a special case with livecds where no hdd_used is detected
5346                         if ( size > 0 && hddused == "na" ) {
5347                                 size = sprintf( "%.1f", size )
5348                                 print size "GB,-"
5349                         }
5350                         else if ( size > 0 && workingUsed > 0 ) {
5351                                 diskUsed = workingUsed*100/size  # calculate used percentage
5352                                 diskUsed = sprintf( "%.1f", diskUsed )
5353                                 size = sprintf( "%.1f", size )
5354                                 print size "GB," diskUsed "% used"
5355                         }
5356                         else {
5357                                 print "NA,-" # print an empty array, this will be further handled in the print out function
5358                         }
5359                 }' $FILE_PARTITIONS ) )
5360                 log_function_data 'cat' "$FILE_PARTITIONS"
5361         fi
5362         IFS="$ORIGINAL_IFS"
5363         temp_array=${A_HDD_DATA[@]}
5364         log_function_data "A_HDD_DATA: $temp_array"
5365         eval $LOGFE
5366 }
5367
5368 ## fills out the A_HDD_DATA array with disk names
5369 get_hard_drive_data_advanced()
5370 {
5371         eval $LOGFS
5372         local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j=''
5373         local sd_ls_by_id='' ls_disk_by_id='' usb_exists='' temp_array=''
5374
5375         ## check for all ide type drives, non libata, only do it if hdx is in array
5376         ## this is now being updated for new /sys type paths, this may handle that ok too
5377         if [[ -n $( grep -E 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
5378                 # remember, we're using the last array item to store the total size of disks
5379                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
5380                 do
5381                         IFS=","
5382                         a_temp_working=( ${A_HDD_DATA[i]} )
5383                         IFS="$ORIGINAL_IFS"
5384                         if [[ -n $( grep -E '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];then
5385                                 if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then
5386                                         a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )"
5387                                 else
5388                                         a_temp_working[2]="Name n/a"
5389                                 fi
5390                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
5391                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
5392                                 do
5393                                         if [[ $j -gt 0 ]];then
5394                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
5395                                         else
5396                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
5397                                         fi
5398                                 done
5399                         fi
5400                 done
5401         fi
5402
5403         ## then handle libata names
5404         # first get the ata device names, put them into an array
5405         IFS=$'\n'
5406         if [[ $B_SCSI_FILE == 'true' ]]; then
5407                 a_temp_scsi=( $( gawk  '
5408                 BEGIN {
5409                         IGNORECASE=1
5410                 }
5411                 /host/ {
5412                         getline a[$0]
5413                         getline b[$0]
5414                 }
5415                 END {
5416                         for (i in a) {
5417                                 if (b[i] ~ / *type: *direct-access.*/) {
5418                                         #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i])
5419                                         #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] )
5420                                         # the vendor: string is useless, and is a bug, ATA is not a vendor for example
5421                                         c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] )
5422                                         gsub(/,/, " ", c)
5423                                         gsub(/^ +| +$/, "", c)
5424                                         gsub(/ [ \t]+/, " ", c)
5425                                         #print a[i]
5426                                         # we actually want this data, so leaving this off for now
5427 #                                       if (c ~ /\<flash\>|\<pendrive\>|memory stick|memory card/) {
5428 #                                               continue
5429 #                                       }
5430                                         print c
5431                                 }
5432                         }
5433                 }' $FILE_SCSI ) )
5434                 log_function_data 'cat' "$FILE_SCSI"
5435         fi
5436         IFS="$ORIGINAL_IFS"
5437
5438         ## then we'll loop through that array looking for matches.
5439         if [[ -n $( grep -E 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
5440                 # first pack the main ls variable so we don't have to keep using ls /dev...
5441                 # not all systems have /dev/disk/by-id
5442                 ls_disk_by_id="$( ls -l /dev/disk/by-id 2>/dev/null )"
5443                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
5444                 do
5445                         if [[ -n $( grep -E '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then
5446                                 IFS=","
5447                                 a_temp_working=( ${A_HDD_DATA[$i]} )
5448                                 IFS="$ORIGINAL_IFS"
5449                                 # /sys/block/[sda,hda]/device/model
5450                                 # this is handles the new /sys data types first
5451                                 if [[ -e /sys/block/${a_temp_working[0]}/device/model ]];then
5452                                         temp_name="$( remove_erroneous_chars /sys/block/${a_temp_working[0]}/device/model )"
5453                                         temp_name=$( tr ' ' '_' <<< $temp_name | cut -d '-' -f 1 )
5454                                 elif [[ ${#a_temp_scsi[@]} -gt 0 ]];then
5455                                         for (( j=0; j < ${#a_temp_scsi[@]}; j++ ))
5456                                         do
5457                                                 ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
5458                                                 # discovered disk name AND ends with the correct identifier, sdx
5459                                                 # get rid of whitespace for some drive names and ids, and extra data after - in name
5460                                                 temp_name=$( tr ' ' '_' <<< ${a_temp_scsi[$j]} | cut -d '-' -f 1 )
5461                                                 sd_ls_by_id=$( grep -Em1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
5462
5463                                                 if [[ -n $sd_ls_by_id ]];then
5464                                                         temp_name=${a_temp_scsi[$j]}
5465                                                         break
5466                                                 else
5467                                                         # test to see if we can get a better name output when null
5468                                                         if [[ -n $temp_name ]];then
5469                                                                 temp_name=$temp_name
5470                                                         fi
5471                                                 fi
5472                                         done
5473                                 fi
5474                                 
5475                                 if [[ -z $temp_name ]];then
5476                                         temp_name="Name n/a"
5477                                 else 
5478                                         usb_exists=$( grep -Em1 "usb-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
5479                                         if [[ -n $usb_exists ]];then
5480                                                 a_temp_working[3]='USB'
5481                                         fi
5482                                 fi
5483                                 a_temp_working[2]=$temp_name
5484                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
5485                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
5486                                 do
5487                                         if [[ $j -gt 0 ]];then
5488                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
5489                                         else
5490                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
5491                                         fi
5492                                 done
5493                         fi
5494                 done
5495                 unset ls_disk_by_id # and then let's dump the data we don't need
5496         fi
5497         temp_array=${A_HDD_DATA[@]}
5498         log_function_data "A_HDD_DATA: $temp_array"
5499         eval $LOGFE
5500 }
5501
5502 # args: $1 - which drive to get serial number of
5503 get_hdd_serial_number()
5504 {
5505         eval $LOGFS
5506         
5507         local hdd_serial=''
5508         
5509         get_partition_dev_data 'id'
5510         
5511         # lrwxrwxrwx 1 root root  9 Apr 26 09:32 scsi-SATA_ST3160827AS_5MT2HMH6 -> ../../sdc
5512         # exit on the first instance
5513         hdd_serial=$( gawk '
5514         /'$1'$/ {
5515                 serial=gensub( /^(.+)_([^_]+)$/, "\\2", 1, $9 )
5516                 print serial
5517                 exit
5518         }' <<< "$DEV_DISK_ID" )
5519         
5520         echo $hdd_serial
5521         log_function_data "hdd serial: $hdd_serial"
5522         eval $LOGFE
5523 }
5524
5525 # a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers.
5526 # args: $1 - /dev/<disk> to be tested for
5527 get_hdd_temp_data()
5528 {
5529         eval $LOGFS
5530         local hdd_temp='' sudo_command='' 
5531
5532         if [[ $B_HDDTEMP_TESTED != 'true' ]];then
5533                 B_HDDTEMP_TESTED='true'
5534                 HDDTEMP_PATH=$( type -p hddtemp )
5535         fi
5536         if [[ $B_SUDO_TESTED != 'true' ]];then
5537                 B_SUDO_TESTED='true'
5538                 SUDO_PATH=$( type -p sudo )
5539         fi
5540         
5541         if [[ -n $HDDTEMP_PATH && -n $1 ]];then
5542                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
5543                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
5544                 # important: -n makes it non interactive, no prompt for password
5545                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
5546                         sudo_command='sudo -n '
5547                 fi
5548                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
5549                 hdd_temp=$( eval $sudo_command $HDDTEMP_PATH -nq -u C $1 )
5550                 if [[ -n $hdd_temp && -n $( grep -E '^([0-9\.]+)$' <<< $hdd_temp ) ]];then
5551                         echo $hdd_temp
5552                 fi
5553         fi
5554         eval $LOGFE
5555 }
5556
5557 get_init_data()
5558 {
5559         eval $LOGFS
5560         
5561         local init_type='' init_version='' rc_type='' rc_version='' temp_array=''
5562         local ls_run='' strings_init_version=''
5563         local runlevel=$( get_runlevel_data )
5564         local default_runlevel=$( get_runlevel_default )
5565         
5566         # this test is pretty solid, if pid 1 is owned by systemd, it is systemd
5567         # otherwise that is 'init', which covers the rest of the init systems, I think anyway.
5568         # more data may be needed for other init systems.
5569         if [[ -e /proc/1/comm && -n $( grep -s 'systemd' /proc/1/comm ) ]];then
5570                 init_type='systemd'
5571                 if [[ -n $( type -p systemd ) ]];then
5572                         init_version=$( get_de_app_version 'systemd' '^systemd' '2' )
5573                 fi
5574                 if [[ -z $init_version && -n $( type -p systemctl ) ]];then
5575                         init_version=$( get_de_app_version 'systemctl' '^systemd' '2' )
5576                 fi
5577         else
5578                 ls_run=$(ls /run)
5579                 # note: upstart-file-bridge.pid upstart-socket-bridge.pid upstart-udev-bridge.pid
5580                 if [[ -n $( /sbin/init --version 2>/dev/null | grep 'upstart' ) ]];then
5581                         init_type='Upstart'
5582                         # /sbin/init --version == init (upstart 1.12.1)
5583                         init_version=$( get_de_app_version 'init' 'upstart' '3' )
5584                 elif [[ -n $( type -p epoch ) ]];then
5585                         init_type='Epoch'
5586                         # epoch version == Epoch Init System 1.0.1 "Sage"
5587                         init_version=$( get_de_app_version 'epoch' '^Epoch' '4' )
5588                 # missing data: 
5589                 # http://smarden.org/runit/sv.8.html
5590                 elif [[ -e /sbin/runit-init || -e /etc/runit || -n $( type -p sv ) ]];then
5591                         init_type='runit' # lower case
5592                         # no data on version yet
5593                 elif [[ -f /etc/inittab ]];then
5594                         init_type='SysVinit'
5595                         if [[ -n $( type -p strings ) ]];then
5596                                 strings_init_version="$( strings /sbin/init | grep -E 'version[[:space:]]+[0-9]' )"
5597                         fi
5598                         if [[ -n $strings_init_version ]];then
5599                                 init_version=$( gawk '{print $2}' <<< "$strings_init_version" )
5600                         fi
5601                 # freebsd at least
5602                 elif [[ -f /etc/ttys ]];then
5603                         init_type='init (bsd)'
5604                 fi
5605                 
5606                 if [[ -n $( grep 'openrc' <<< "$ls_run" ) ]];then
5607                         rc_type='OpenRC'
5608                         # /sbin/openrc --version == openrc (OpenRC) 0.13
5609                         if [[ -n $( type -p openrc ) ]];then
5610                                 rc_version=$( get_de_app_version 'openrc' '^openrc' '3' )
5611                         # /sbin/rc --version == rc (OpenRC) 0.11.8 (Gentoo Linux)
5612                         elif [[ -n $( type -p rc ) ]];then
5613                                 rc_version=$( get_de_app_version 'rc' '^rc' '3' )
5614                         fi
5615                 ## assume sysvrc, but this data is too buggy and weird and inconsistent to have meaning
5616                 # leaving this off for now
5617 #               elif [[ -f /etc/inittab ]];then
5618 #                       rc_type='SysVrc'
5619 #                       # this is a guess that rc and init are same versions, may need updates / fixes
5620 #                       rc_version=$init_version
5621                 fi
5622         fi
5623         
5624         IFS=$'\n'
5625         
5626         A_INIT_DATA=( 
5627         "$init_type"
5628         "$init_version"
5629         "$rc_type"
5630         "$rc_version"
5631         "$runlevel"
5632         "$default_runlevel" )
5633         
5634         IFS="$ORIGINAL_IFS"
5635         
5636         temp_array=${A_INIT_DATA[@]}
5637         log_function_data "A_INIT_DATA: $temp_array"
5638         
5639         eval $LOGFE
5640 }
5641
5642 get_kernel_version()
5643 {
5644         eval $LOGFS
5645         
5646         local kernel_version='' ksplice_kernel_version=''
5647         
5648         kernel_version=$( uname -rm )
5649         
5650         if [[ -n $( type -p uptrack-uname ) && -n $kernel_version ]];then
5651                 ksplice_kernel_version=$( uptrack-uname -rm )
5652                 if [[ $kernel_version != $ksplice_kernel_version ]];then
5653                         kernel_version="$ksplice_kernel_version (ksplice)"
5654                 fi
5655         fi
5656         log_function_data "kernel_version: $kernel_version - ksplice_kernel_version: $ksplice_kernel_version"
5657         
5658         echo $kernel_version
5659         
5660         eval $LOGFE
5661 }
5662
5663 # args: $1 - v/n 
5664 get_lspci_data()
5665 {
5666         eval $LOGFS
5667         local lspci_data=''
5668
5669         if [[ $B_LSPCI == 'true' ]];then
5670                 lspci_data="$( lspci -$1 | gawk '{
5671                         gsub(/\(prog-if[^)]*\)/,"")
5672                         sub(/^0000:/, "", $0) # seen case where the 0000: is prepended, rare, but happens
5673                         print
5674                 }' )"
5675         fi
5676         
5677         echo "$lspci_data"
5678         log_function_data 'raw' "lspci_data $1:\n$lspci_data"
5679         eval $LOGFE
5680 }
5681
5682 # args: $1 - busid
5683 get_lspci_chip_id()
5684 {
5685         eval $LOGFS
5686         
5687         local chip_id=''
5688         
5689         chip_id=$( gawk '
5690         /^'$1'/ {
5691                 if ( $3 != "" ) {
5692                         print $3
5693                 }
5694         }' <<< "$Lspci_n_Data" )
5695         
5696         echo $chip_id
5697         
5698         eval $LOGFE
5699 }
5700
5701 get_machine_data()
5702 {
5703         eval $LOGFS
5704         local temp_array='' separator='' id_file='' file_data='' array_string=''
5705         local id_dir='/sys/class/dmi/id/' dmi_data='' 
5706         local machine_files="
5707         sys_vendor product_name product_version product_serial product_uuid 
5708         board_vendor board_name board_version board_serial 
5709         bios_vendor bios_version bios_date 
5710         "
5711
5712         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
5713                 machine_files="$machine_files
5714                 chassis_vendor chassis_type chassis_version chassis_serial
5715                 "
5716         fi
5717         if [[ -d $id_dir ]];then
5718                 for id_file in $machine_files
5719                 do
5720                         file_data=''
5721                         if [[ -r $id_dir$id_file ]];then
5722                                 file_data=$( gawk '
5723                                 BEGIN {
5724                                         IGNORECASE=1
5725                                 }
5726                                 {
5727                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
5728                                         gsub(/,/, " ", $0)
5729                                         # yes, there is a typo in a user data set, unknow
5730                                         # Base Board Version|Base Board Serial Number
5731                                         # Chassis Manufacturer|Chassis Version|Chassis Serial Number
5732                                         # System manufacturer|System Product Name|System Version
5733                                         # To Be Filled By O.E.M.
5734                                         sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", $0) 
5735                                         gsub(/bios|acpi/, "", $0)
5736                                         sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
5737                                         gsub(/^ +| +$/, "", $0)
5738                                         gsub(/ [ \t]+/, " ", $0)
5739                                         print $0
5740                                 }' < $id_dir$id_file )
5741                         fi
5742                         array_string="$array_string$separator$file_data"
5743                         separator=','
5744                 done
5745         else
5746                 get_dmidecode_data
5747                 if [[ -n $DMIDECODE_DATA ]];then
5748                         if [[ $B_ROOT == 'true' ]];then
5749                                 # this handles very old systems, like Lenny 2.6.26, with dmidecode, but no data
5750                                 if [[ -n $( grep -i 'no smbios ' <<< "$DMIDECODE_DATA" ) ]];then
5751                                         array_string='dmidecode-no-smbios-dmi-data'
5752                                 # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
5753                                 else
5754                                         array_string=$( gawk -F ':' '
5755                                         BEGIN {
5756                                                 IGNORECASE=1
5757                                                 baseboardManufacturer=""
5758                                                 baseboardProductName=""
5759                                                 baseboardSerialNumber=""
5760                                                 baseboardVersion=""
5761                                                 biosReleaseDate=""
5762                                                 biosRevision="" # only available from dmidecode
5763                                                 biosRomSize="" # only available from dmidecode
5764                                                 biosVendor=""
5765                                                 biosVersion=""
5766                                                 chassisManufacturer=""
5767                                                 chassisSerialNumber=""
5768                                                 chassisType=""
5769                                                 chassisVersion=""
5770                                                 systemManufacturer=""
5771                                                 systemProductName=""
5772                                                 systemVersion=""
5773                                                 systemSerialNumber=""
5774                                                 systemUuid=""
5775                                                 bItemFound="" # we will only output if at least one item was found
5776                                                 fullString=""
5777                                                 testString=""
5778                                                 bSys=""
5779                                                 bCha=""
5780                                                 bBio=""
5781                                                 bBas=""
5782                                         }
5783                                         /^Bios Information/ {
5784                                                 while ( getline && !/^$/ ) {
5785                                                         if ( $1 ~ /^Release Date/ ) { biosReleaseDate=$2 }
5786                                                         if ( $1 ~ /^BIOS Revision/ ) { biosRevision=$2 }
5787                                                         if ( $1 ~ /^ROM Size/ ) { biosRomSize=$2 }
5788                                                         if ( $1 ~ /^Vendor/ ) { biosVendor=$2 }
5789                                                         if ( $1 ~ /^Version/ ) { biosVersion=$2 }
5790                                                 }
5791                                                 testString=biosReleaseDate biosRevision biosRomSize biosVendor biosVersion
5792                                                 if ( testString != ""  ) {
5793                                                         bItemFound="true"
5794                                                 }
5795                                                 bBio="true"
5796                                         }
5797                                         /^Base Board Information/ {
5798                                                 while ( getline && !/^$/ ) {
5799                                                         if ( $1 ~ /^Manufacturer/ ) { baseboardManufacturer=$2 }
5800                                                         if ( $1 ~ /^Product Name/ ) { baseboardProductName=$2 }
5801                                                         if ( $1 ~ /^Serial Number/ ) { baseboardSerialNumber=$2 }
5802                                                 }
5803                                                 testString=baseboardManufacturer baseboardProductName baseboardSerialNumber
5804                                                 if ( testString != ""  ) {
5805                                                         bItemFound="true"
5806                                                 }
5807                                                 bBas="true"
5808                                         }
5809                                         /^Chassis Information/ {
5810                                                 while ( getline && !/^$/ ) {
5811                                                         if ( $1 ~ /^Manufacturer/ ) { chassisManufacturer=$2 }
5812                                                         if ( $1 ~ /^Serial Number/ ) { chassisSerialNumber=$2 }
5813                                                         if ( $1 ~ /^Type/ ) { chassisType=$2 }
5814                                                         if ( $1 ~ /^Version/ ) { chassisVersion=$2 }
5815                                                 }
5816                                                 testString=chassisManufacturer chassisSerialNumber chassisType chassisVersion
5817                                                 if ( testString != ""  ) {
5818                                                         bItemFound="true"
5819                                                 }
5820                                                 bCha="true"
5821                                         }
5822                                         /^System Information/ {
5823                                                 while ( getline && !/^$/ ) {
5824                                                         if ( $1 ~ /^Manufacturer/ ) { systemManufacturer=$2 }
5825                                                         if ( $1 ~ /^Product Name/ ) { systemProductName=$2 }
5826                                                         if ( $1 ~ /^Version/ ) { systemVersion=$2 }
5827                                                         if ( $1 ~ /^Serial Number/ ) { systemSerialNumber=$2 }
5828                                                         if ( $1 ~ /^UUID/ ) { systemUuid=$2 }
5829                                                 }
5830                                                 testString=systemManufacturer systemProductName systemVersion systemSerialNumber systemUuid
5831                                                 if ( testString != ""  ) {
5832                                                         bItemFound="true"
5833                                                 }
5834                                                 bSys="true"
5835                                         }
5836                                         ( bSys == "true" && bCha="true" && bBio == "true" && bBas == "true" ) {
5837                                                 exit # stop the loop
5838                                         }
5839                                         END {
5840                                                 if ( bItemFound == "true" ) {
5841                                                         fullString = systemManufacturer "," systemProductName "," systemVersion "," systemSerialNumber 
5842                                                         fullString = fullString "," systemUuid "," baseboardManufacturer "," baseboardProductName 
5843                                                         fullString = fullString "," baseboardVersion "," baseboardSerialNumber "," biosVendor
5844                                                         fullString = fullString "," biosVersion "," biosReleaseDate "," chassisManufacturer
5845                                                         fullString = fullString "," chassisType "," chassisVersion "," chassisSerialNumber 
5846                                                         fullString = fullString ","  biosRevision "," biosRomSize
5847                                                         
5848                                                         print fullString
5849                                                 }
5850                                         }' <<< "$DMIDECODE_DATA" )
5851                                 fi
5852                         else
5853                                 array_string='dmidecode-non-root-user'
5854                         fi
5855                 fi
5856         fi
5857         IFS=','
5858         A_MACHINE_DATA=( $array_string )
5859         IFS="$ORIGINAL_IFS"
5860         temp_array=${A_MACHINE_DATA[@]}
5861 #       echo ${temp_array[@]}
5862         log_function_data "A_MACHINE_DATA: $temp_array"
5863         eval $LOGFE
5864 }
5865 # B_ROOT='true';get_machine_data;exit
5866 ## return memory used/installed
5867 get_memory_data()
5868 {
5869         eval $LOGFS
5870         local memory='' memory_full='' 
5871         if [[ $B_MEMINFO_FILE == 'true' ]];then
5872                 memory=$( gawk '
5873                 /^MemTotal:/ {
5874                         tot = $2
5875                 }
5876                 /^(MemFree|Buffers|Cached):/ {
5877                         notused+=$2
5878                 }
5879                 END {
5880                         used = tot - notused
5881                         printf("%.1f/%.1fMB\n", used/1024, tot/1024)
5882                 }' $FILE_MEMINFO )
5883                 log_function_data 'cat' "$FILE_MEMINFO"
5884         elif [[ $B_SYSCTL == 'true' && -n $Sysctl_a_Data ]];then
5885                 local gawk_fs=': '
5886         
5887                 if [[ $BSD_VERSION == 'openbsd' ]];then
5888                         gawk_fs='='
5889                 fi
5890                 memory=$( grep -i 'mem' <<< "$Sysctl_a_Data" | gawk -F "$gawk_fs"  '
5891                 BEGIN {
5892                         realMemory=""
5893                         freeMemory=""
5894                 }
5895                 # freebsd seems to use bytes here
5896                 /^hw.physmem/ {
5897                         gsub(/^[^0-9]+|[^0-9]+$/,"",$2)
5898                         realMemory = $2/1024
5899                         if ( freeMemory != "" ) {
5900                                 exit
5901                         }
5902                 }
5903                 # But, it uses K here. Openbsd does not seem to have this item
5904                 # this can be either: Free Memory OR Free Memory Pages
5905                 $1 ~ /^Free Memory/ {
5906                         gsub(/[^0-9]/,"",$NF)
5907                         freeMemory = $NF
5908                         if ( realMemory != "" ) {
5909                                 exit
5910                         }
5911                 }
5912                 END {
5913                         # hack: temp fix for openbsd: in case no free mem was detected but we have physmem
5914                         if ( freeMemory == "" && realMemory != "" ) {
5915                                 printf("NA/%.1fMB\n", realMemory/1024)
5916                         }
5917                         else if ( freeMemory != "" && realMemory != "" ) {
5918                                 used = realMemory - freeMemory
5919                                 printf("%.1f/%.1fMB\n", used/1024, realMemory/1024)
5920                         }
5921                 }' )
5922         fi
5923         echo "$memory"
5924         log_function_data "memory: $memory"
5925         eval $LOGFE
5926 }
5927
5928 # process and return module version data
5929 get_module_version_number()
5930 {
5931         eval $LOGFS
5932         local module_version=''
5933         
5934         if [[ $B_MODINFO_TESTED != 'true' ]];then
5935                 B_MODINFO_TESTED='true'
5936                 MODINFO_PATH=$( type -p modinfo )
5937         fi
5938
5939         if [[ -n $MODINFO_PATH ]];then
5940                 module_version=$( $MODINFO_PATH $1 2>/dev/null | gawk '
5941                 BEGIN {
5942                         IGNORECASE=1
5943                 }
5944                 /^version/ {
5945                         gsub(/,/, " ", $2)
5946                         gsub(/^ +| +$/, "", $2)
5947                         gsub(/ [ \t]+/, " ", $2)
5948                         print $2
5949                 }
5950                 ' )
5951         fi
5952
5953         echo "$module_version"
5954         log_function_data "module_version: $module_version"
5955         eval $LOGFE
5956 }
5957
5958 ## create array of network cards
5959 get_networking_data()
5960 {
5961         eval $LOGFS
5962         
5963         local B_USB_NETWORKING='false' temp_array=''
5964         
5965         IFS=$'\n'
5966         A_NETWORK_DATA=( $( 
5967         echo "$Lspci_v_Data" | gawk '
5968         BEGIN {
5969                 IGNORECASE=1
5970                 counter=0 # required to handle cases of > 1 instance of the same chipset
5971         }
5972         /^[0-9a-f:\.]+ (ethernet|network) (controller|bridge)/ || /^[0-9a-f:\.]+ [^:]+: .*(ethernet|network).*$/ {
5973                 nic=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
5974                 #gsub(/realtek semiconductor/, "Realtek", nic)
5975                 #gsub(/davicom semiconductor/, "Davicom", nic)
5976                 # The doublequotes are necessary because of the pipes in the variable.
5977                 gsub(/'"$BAN_LIST_NORMAL"'/, "", nic)
5978                 gsub(/,/, " ", nic)
5979                 gsub(/^ +| +$/, "", nic)
5980                 gsub(/ [ \t]+/, " ", nic)
5981                 # construct a unique string ending for each chipset detected, this allows for
5982                 # multiple instances of the same exact chipsets, ie, dual gigabit 
5983                 nic = nic "~~" counter++
5984                 aPciBusId[nic] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
5985                 # I do not understand why incrementing a string index makes sense? 
5986                 eth[nic]++ 
5987                 while ( getline && !/^$/ ) {
5988                         gsub(/,/, "", $0)
5989                         if ( /I\/O/ ) {
5990                                 ports[nic] = ports[nic] $4 " "
5991                         }
5992                         if ( /driver in use/ ) {
5993                                 drivers[nic] = drivers[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
5994                         }
5995                         else if ( /kernel modules/ ) {
5996                                 modules[nic] = modules[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
5997                         }
5998                 }
5999         }
6000
6001         END {
6002                 j=0
6003                 for (i in eth) {
6004                         useDrivers=""
6005                         usePorts=""
6006                         useModules=""
6007                         usePciBusId=""
6008
6009                         if ( eth[i] > 1 ) {
6010                                 a[j] = eth[i] "x " i
6011                         }
6012                         else {
6013                                 a[j] = i
6014                         }       
6015                         ## note: this loses the plural ports case, is it needed anyway?
6016                         if ( ports[i] != "" ) {
6017                                 usePorts = ports[i]
6018                         }
6019                         if ( drivers[i] != "" ) {
6020                                 useDrivers = drivers[i]
6021                         }
6022                         if ( modules[i] != "" ) {
6023                                 useModules = modules[i]
6024                         }
6025                         if ( aPciBusId[i] != "" ) {
6026                                 usePciBusId = aPciBusId[i]
6027                         }
6028                         # create array primary item for master array
6029                         # and strip out the counter again, this handled dual cards with same chipset
6030                         sub( /~~[0-9]+$/, "", a[j] )
6031                         sub( / $/, "", usePorts ) # clean off trailing whitespace
6032                         print a[j] "," useDrivers "," usePorts "," useModules, "," usePciBusId
6033                         j++
6034                 }
6035         }' ) )
6036         IFS="$ORIGINAL_IFS"
6037         get_networking_usb_data
6038         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' || $B_USB_NETWORKING == 'true' ]];then
6039                 get_network_advanced_data
6040         fi
6041         temp_array=${A_NETWORK_DATA[@]}
6042         log_function_data "A_NETWORK_DATA: $temp_array"
6043         
6044         eval $LOGFE
6045 }
6046
6047 get_network_advanced_data()
6048 {
6049         eval $LOGFS
6050         local a_network_adv_working='' if_path='' working_path='' working_uevent_path='' dir_path=''
6051         local if_id='' speed='' duplex='' mac_id='' oper_state=''  chip_id=''
6052         local usb_data='' usb_vendor='' usb_product='' product_path='' driver_test=''
6053         
6054         for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
6055         do
6056                 IFS=","
6057                 a_network_adv_working=( ${A_NETWORK_DATA[i]} )
6058                 # reset these every go round
6059                 driver_test=''
6060                 if_id='' 
6061                 speed='' 
6062                 duplex='' 
6063                 mac_id='' 
6064                 oper_state=''
6065                 usb_data=''
6066                 chip_id=''
6067                 if [[ -z $( grep '^usb-' <<< ${a_network_adv_working[4]} ) ]];then
6068                         # note although this may exist technically don't use it, it's a virtual path
6069                         # and causes weird cat errors when there's a missing file as well as a virtual path
6070                         # /sys/bus/pci/devices/0000:02:02.0/net/eth1
6071                         # real paths are: /sys/devices/pci0000:00/0000:00:1e/0/0000:02:02.0/net/eth1/uevent
6072                         # and on older debian kernels: /sys/devices/pci0000:00/0000:02:02.0/net:eth1/uevent
6073                         # but broadcom shows this sometimes:
6074                         # /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ssb0:0/uevent:['DRIVER=b43', 'MODALIAS=ssb:v4243id0812rev0D']:
6075                         working_path="/sys/bus/pci/devices/0000:${a_network_adv_working[4]}"
6076                         # now we want the real one, that xiin also displays, without symbolic links.
6077                         if [[ -e $working_path ]];then
6078                                 working_path=$( readlink -f $working_path 2>/dev/null )
6079                                 # sometimes there is another directory between the path and /net
6080                                 if [[ ! -e $working_path/net ]];then
6081                                         # using find here, probably will need to also use it in usb part since the grep
6082                                         # method seems to not be working now. Slice off the rest, which leaves the basic path
6083                                         working_path=$( find $working_path/*/net/*/uevent 2>/dev/null | \
6084                                         sed 's|/net.*||' )
6085                                 fi
6086                         fi
6087                         # working_path=$( ls /sys/devices/pci*/*/0000:${a_network_adv_working[4]}/net/*/uevent  )
6088                 else
6089                         # now we'll use the actual vendor:product string instead
6090                         usb_data=${a_network_adv_working[10]}
6091                         usb_vendor=$( cut -d ':' -f 1 <<< $usb_data )
6092                         usb_product=$( cut -d ':' -f 2 <<< $usb_data )
6093                         # this grep returns the path plus the contents of the file, with a colon separator, so slice that off
6094                         # /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/idVendor
6095                         working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/*/idVendor | \
6096                         sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
6097                         # try an alternate path if first one doesn't work
6098                         # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/idVendor
6099                         if [[ -z $working_path ]];then
6100                                 working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/idVendor | \
6101                                 sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
6102                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/idProduct | \
6103                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
6104                         else
6105                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/*/idProduct | \
6106                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
6107                         fi
6108                         
6109                         # make sure it's the right product/vendor match here, it will almost always be but let's be sure
6110                         if [[ -n $working_path && -n $product_path ]] && [[ $working_path == $product_path ]];then
6111                         #if [[ -n $working_path ]];then
6112                                 # now ls that directory and get the numeric starting sub directory and that should be the full path
6113                                 # to the /net directory part
6114                                 dir_path=$( ls ${working_path} 2>/dev/null | grep -sE '^[0-9]' )
6115                                 working_uevent_path="${working_path}${dir_path}"
6116                         fi
6117                 fi
6118                 # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/uevent grep for DRIVER=
6119                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/1-1:1.0/uevent
6120                 if [[ -n $usb_data ]];then
6121                         driver_test=$( grep -si 'DRIVER=' $working_uevent_path/uevent | cut -d '=' -f 2 )
6122                         if [[ -n $driver_test ]];then
6123                                 a_network_adv_working[1]=$driver_test
6124                         fi
6125                 fi
6126                 log_function_data "PRE: working_path: $working_path\nworking_uevent_path: $working_uevent_path"
6127                 
6128                 # this applies in two different cases, one, default, standard, two, for usb, this is actually
6129                 # the short path, minus the last longer numeric directory name, ie: 
6130                 # from debian squeeze 2.6.32-5-686: 
6131                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/net/wlan0/address
6132                 if [[ -e $working_path/net ]];then
6133                         if_path=$( ls $working_path/net 2>/dev/null )
6134                         if_id=$if_path
6135                         working_path=$working_path/net/$if_path
6136                 # this is the normal usb detection if the first one didn't work
6137                 elif [[ -n $usb_data && -e $working_uevent_path/net ]];then
6138                         if_path=$( ls $working_uevent_path/net 2>/dev/null )
6139                         if_id=$if_path
6140                         working_path=$working_uevent_path/net/$if_path
6141                 # 2.6.32 debian lenny kernel shows not: /net/eth0 but /net:eth0
6142                 else
6143                         if_path=$( ls $working_path 2>/dev/null | grep 'net:' )
6144                         if_id=$( cut -d ':' -f 2 <<< "$if_path" )
6145                         working_path=$working_path/$if_path
6146                 fi
6147                 log_function_data "POST: working_path: $working_path\nif_path: $if_path - if_id: $if_id"
6148                 
6149                 if [[ -n $if_path ]];then
6150                         if [[ -r $working_path/speed ]];then
6151                                 speed=$( cat $working_path/speed 2>/dev/null )
6152                         fi
6153                         if [[ -r $working_path/duplex ]];then
6154                                 duplex=$( cat $working_path/duplex 2>/dev/null )
6155                         fi
6156                         if [[ -r $working_path/address ]];then
6157                                 mac_id=$( cat $working_path/address 2>/dev/null )
6158                         fi
6159                         if [[ -r $working_path/operstate ]];then
6160                                 oper_state=$( cat $working_path/operstate 2>/dev/null )
6161                         fi
6162                 fi
6163                 
6164                 if [[ -n ${a_network_adv_working[10]} ]];then
6165                         chip_id=${a_network_adv_working[10]}
6166                 fi
6167                 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
6168                 IFS="$ORIGINAL_IFS"
6169         done
6170
6171         eval $LOGFE
6172 }
6173
6174 get_networking_usb_data()
6175 {
6176         eval $LOGFS
6177         local lsusb_path='' lsusb_data='' a_usb='' array_count=''
6178         
6179         # now we'll check for usb wifi, a work in progress
6180         # USB_NETWORK_SEARCH
6181         # alsa usb detection by damentz
6182         # for every sound card symlink in /proc/asound - display information about it
6183         lsusb_path=$( type -p lsusb )
6184         # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue
6185         if [[ -n $lsusb_path ]]; then
6186                 # send error messages of lsusb to /dev/null as it will display a bunch if not a super user
6187                 lsusb_data="$( $lsusb_path 2>/dev/null )"
6188                 # also, find the contents of usbid in lsusb and print everything after the 7th word on the
6189                 # corresponding line. Finally, strip out commas as they will change the driver :)
6190                 if [[ -n $lsusb_data ]];then
6191                         IFS=$'\n'
6192                         a_usb=( $( 
6193                         gawk '
6194                         BEGIN {
6195                                 IGNORECASE=1
6196                                 string=""
6197                                 separator=""
6198                         }
6199                         /'"$USB_NETWORK_SEARCH"'/ && !/bluetooth| hub|keyboard|mouse|printer| ps2|reader|scan|storage/ {
6200                                 string=""
6201                                 gsub( /,/, " ", $0 )
6202                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
6203                                 gsub(/ [ \t]+/, " ", $0)
6204                                 #sub(/realtek semiconductor/, "Realtek", $0)
6205                                 #sub(/davicom semiconductor/, "Davicom", $0)
6206                                 #sub(/Belkin Components/, "Belkin", $0)
6207                                 
6208                                 for ( i=7; i<= NF; i++ ) {
6209                                         string = string separator $i
6210                                         separator = " "
6211                                 }
6212                                 if ( $2 != "" ){
6213                                         sub(/:/, "", $4 )
6214                                         print string ",,,,usb-" $2 "-" $4 ",,,,,," $6
6215                                 }
6216                         }' <<< "$lsusb_data" ) )
6217                         IFS="$ORIGINAL_IFS"
6218                         if [[ ${#a_usb[@]} -gt 0 ]];then
6219                                 array_count=${#A_NETWORK_DATA[@]}
6220                                 for (( i=0; i < ${#a_usb[@]}; i++ ))
6221                                 do
6222                                         A_NETWORK_DATA[$array_count]=${a_usb[i]}
6223                                         ((array_count++))
6224                                 done
6225                                 # need this to get the driver data for -N regular output, but no need
6226                                 # to run the advanced stuff unless required
6227                                 B_USB_NETWORKING='true'
6228                         fi
6229                 fi
6230         fi
6231 #       echo $B_USB_NETWORKING
6232         eval $LOGFE
6233 }
6234
6235 get_networking_wan_ip_data()
6236 {
6237         eval $LOGFS
6238         local ip=''
6239
6240         # get ip using wget redirect to stdout. This is a clean, text only IP output url,
6241         # single line only, ending in the ip address. May have to modify this in the future
6242         # to handle ipv4 and ipv6 addresses but should not be necessary.
6243         # awk has bad regex handling so checking it with grep -E instead
6244         # ip=$( echo  2001:0db8:85a3:0000:0000:8a2e:0370:7334 | gawk  --re-interval '
6245         # ip=$( wget -q -O - $WAN_IP_URL | gawk  --re-interval '
6246         ip=$( wget -t 1 -T $WGET_TIMEOUT -q -O - $WAN_IP_URL | gawk  --re-interval '
6247         {
6248                 #gsub("\n","",$2")
6249                 print $NF
6250         }' )
6251         # validate the data
6252         if [[ -z $ip ]];then
6253                 ip='None Detected!'
6254         elif [[ -z $( grep -Es \
6255         '^([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
6256                 ip='IP Source Corrupt!'
6257         fi
6258         echo "$ip"
6259         log_function_data "ip: $ip"
6260         eval $LOGFE
6261 }
6262
6263 get_networking_local_ip_data()
6264 {
6265         eval $LOGFS
6266         
6267         local ip_tool_command=$( type -p ip )
6268         local temp_array='' ip_tool='ip' ip_tool_data=''
6269         # the chances for all new systems to have ip by default are far higher than
6270         # the deprecated ifconfig. Only try for ifconfig if ip is not present in system
6271         if [[ -z $ip_tool_command ]];then
6272                 ip_tool_command=$( type -p ifconfig )
6273                 ip_tool='ifconfig'
6274         else
6275                 ip_tool_command="$ip_tool_command addr"
6276         fi
6277         if [[ -n "$ip_tool_command" ]];then
6278                 if [[ $ip_tool == 'ifconfig' ]];then
6279                         ip_tool_data="$( $ip_tool_command | gawk '
6280                         {
6281                                 line=gensub(/^([a-z]+[0-9][:]?[[:space:]].*)/, "\n\\1", $0)
6282                                 print line
6283                         }' )"
6284                 # note, ip addr does not have proper record separation, so creating new lines explicitly here at start
6285                 # of each IF record item. Also getting rid of the unneeded numeric line starters, now it can be parsed 
6286                 # like ifconfig more or less
6287                 elif [[ $ip_tool == 'ip' ]];then
6288                         ip_tool_data="$( eval ${ip_tool_command} | sed 's/^[0-9]\+:[[:space:]]\+/\n/' )"
6289                 fi
6290         fi
6291         if [[ -z $ip_tool_command ]];then
6292                 A_INTERFACES_DATA=( "Interfaces program 'ip' missing. Please check: $SCRIPT_NAME --recommends" )
6293         elif [[ -n "$ip_tool_data" ]];then
6294                 IFS=$'\n' # $ip_tool_command
6295                 A_INTERFACES_DATA=( $( 
6296                 gawk -v ipTool=$ip_tool -v bsdType=$BSD_TYPE '
6297                 BEGIN {
6298                         IGNORECASE=1
6299                         interface=""
6300                         ifIp=""
6301                         ifIpV6=""
6302                         ifMask=""
6303                 }
6304                 # skip past the lo item
6305                 /^lo/ {
6306                         while (getline && !/^$/ ) {
6307                                 # do nothing, just get past this entry item
6308                         }
6309                 }
6310                 /^[a-zA-Z]+[0-9]/ {
6311                         # not clear on why inet is coming through, but this gets rid of it
6312                         # as first line item.
6313                         gsub(/,/, " ", $0)
6314                         gsub(/^ +| +$/, "", $0)
6315                         gsub(/ [ \t]+/, " ", $0)
6316                         interface = $1
6317                         # prep this this for ip addr: eth0: 
6318                         sub(/:/, "", interface)
6319                         ifIp=""
6320                         ifIpV6=""
6321                         ifMask=""
6322                         aInterfaces[interface]++
6323
6324                         while (getline && !/^$/ ) {
6325                                 if ( ipTool == "ifconfig" ) {
6326                                         if (/inet addr:/) {
6327                                                 ifIp = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 )
6328                                                 if (/mask:/) {
6329                                                         ifMask = gensub( /mask:([0-9\.]+)/, "\\1", "g", $NF )
6330                                                 }
6331                                         }
6332                                         if (/inet6 addr:/) {
6333                                                 ifIpV6 = $3
6334                                         }
6335                                         if ( bsdType == "bsd" ) {
6336                                                 if ( $1 == "inet" ) {
6337                                                         ifIp = $2
6338                                                         if ( $3 == "netmask" ) {
6339                                                                 ifMask = $4
6340                                                         }
6341                                                 }
6342                                                 if ( $0 ~ /inet6.*%/ ) {
6343                                                         sub(/%.*/,"",$2)
6344                                                         ifIpV6 = $2
6345                                                 }
6346                                         }
6347                                 }
6348                                 else if ( ipTool == "ip" ) {
6349                                         if ( $1 == "inet" ) {
6350                                                 ifIp = $2
6351                                         }
6352                                         if ( $1 == "inet6" ) {
6353                                                 ifIpV6 = $2
6354                                         }
6355                                 }
6356                         }
6357                         # slice off the digits that are sometimes tacked to the end of the address, 
6358                         # like: /64 or /24
6359                         sub(/\/[0-9]+/, "", ifIp)
6360                         sub(/\/[0-9]+/, "", ifIpV6)
6361                         ipAddresses[interface] = ifIp "," ifMask "," ifIpV6
6362                 }
6363                 END {
6364                         j=0
6365                         for (i in aInterfaces) {
6366                                 ifData = ""
6367                                 a[j] = i
6368                                 if (ipAddresses[i] != "") {
6369                                         ifData = ipAddresses[i]
6370                                 }
6371                                 # create array primary item for master array
6372                                 # tested needed to avoid bad data from above, if null it is garbage
6373                                 # this is the easiest way to handle junk I found, improve if you want
6374                                 if ( ifData != "" ) {
6375                                         print a[j] "," ifData
6376                                 }
6377                                 j++
6378                         }
6379                 }' <<< "$ip_tool_data" ) )
6380                 IFS="$ORIGINAL_IFS"
6381         else
6382                 A_INTERFACES_DATA=( "Interfaces program $ip_tool present but created no data. " )
6383         fi
6384         temp_array=${A_INTERFACES_DATA[@]}
6385         log_function_data "A_INTERFACES_DATA: $temp_array"
6386         eval $LOGFE
6387 }
6388 # get_networking_local_ip_data;exit
6389
6390 # get_networking_local_ip_data;exit
6391 get_optical_drive_data()
6392 {
6393         eval $LOGFS
6394         
6395         local temp_array='' sys_uevent_path='' proc_cdrom='' link_list=''
6396         local separator='' linked='' disk='' item_string='' proc_info_string='' 
6397         local dev_disks_links="$( ls /dev/dvd* /dev/cd* /dev/scd* 2>/dev/null  )"
6398         # get the actual disk dev location, first try default which is easier to run, need to preserve line breaks
6399         local dev_disks_real="$( echo "$dev_disks_links" | xargs -L 1 readlink 2>/dev/null | sort -u )"
6400         # Some systems don't support xargs -L so we need to do it manually
6401         if [[ -z $dev_disks_real ]];then
6402                 for linked in $dev_disks_links
6403                 do
6404                         disk=$( readlink $linked 2>/dev/null )
6405                         if [[ -n $disk ]];then
6406                                 disk=$( basename $disk ) # puppy shows this as /dev/sr0, not sr0
6407                                 if [[ -z $dev_disks_real || -z $( grep $disk <<< $dev_disks_real ) ]];then
6408                                         # need line break IFS for below, no white space
6409                                         dev_disks_real="$dev_disks_real$separator$disk"
6410                                         separator=$'\n'
6411                                 fi
6412                         fi
6413                 done
6414                 dev_disks_real="$( sort -u <<< "$dev_disks_real" )"
6415                 linked=''
6416                 disk=''
6417                 separator=''
6418         fi
6419
6420         # A_OPTICAL_DRIVE_DATA indexes: not going to use all these, but it's just as easy to build the full
6421         # data array and use what we need from it as to update it later to add features or items
6422         # 0 - true dev path, ie, sr0, hdc
6423         # 1 - dev links to true path
6424         # 2 - device vendor - for hdx drives, vendor model are one string from proc
6425         # 3 - device model
6426         # 4 - device rev version
6427         # 5 - speed
6428         # 6 - multisession support
6429         # 7 - MCN support
6430         # 8 - audio read
6431         # 9 - cdr
6432         # 10 - cdrw
6433         # 11 - dvd read
6434         # 12 - dvdr
6435         # 13 - dvdram
6436         # 14 - state
6437
6438         if [[ -n $dev_disks_real ]];then
6439                 if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
6440                         proc_cdrom="$( cat /proc/sys/dev/cdrom/info 2>/dev/null )"
6441                 fi
6442                 IFS=$'\n'
6443                 A_OPTICAL_DRIVE_DATA=( $(
6444                 for disk in $dev_disks_real
6445                 do
6446                         for linked in $dev_disks_links 
6447                         do
6448                                 if [[ -n $( readlink $linked | grep $disk ) ]];then
6449                                         linked=$( basename $linked )
6450                                         link_list="$link_list$separator$linked"
6451                                         separator='~'
6452                                 fi
6453                         done
6454                         item_string="$disk,$link_list"
6455                         link_list=''
6456                         linked=''
6457                         separator=''
6458                         vendor=''
6459                         model=''
6460                         proc_info_string=''
6461                         rev_number=''
6462                         state=""
6463                         sys_path=''
6464                         # this is only for new sd type paths in /sys, otherwise we'll use /proc/ide
6465                         if [[ -z $( grep '^hd' <<< $disk ) ]];then
6466                                 sys_path=$( ls /sys/devices/pci*/*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
6467                                 # no need to test for errors yet, probably other user systems will require some alternate paths though
6468                                 if [[ -n $sys_path ]];then
6469                                         vendor=$( cat $sys_path/vendor 2>/dev/null )
6470                                         model=$( cat $sys_path/model 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6471                                         state=$( cat $sys_path/state 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6472                                         rev_number=$( cat $sys_path/rev 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
6473                                 fi
6474                         elif [[ -e /proc/ide/$disk/model ]];then
6475                                 vendor=$( cat /proc/ide/$disk/model 2>/dev/null )
6476                         fi
6477                         if [[ -n $vendor ]];then
6478                                 vendor=$( gawk '
6479                                 BEGIN {
6480                                         IGNORECASE=1
6481                                 }
6482                                 {
6483                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
6484                                         sub(/TSSTcorp/, "TSST ", $0) # seen more than one of these weird ones
6485                                         gsub(/,/, " ", $0)
6486                                         gsub(/^[[:space:]]*|[[:space:]]*$/, "", $0)
6487                                         gsub(/ [[:space:]]+/, " ", $0)
6488                                         print $0
6489                                 }'      <<< $vendor )
6490                         fi
6491                         # this needs to run no matter if there's proc data or not to create the array comma list
6492                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
6493                                 proc_info_string=$( gawk -v diskId=$disk '
6494                                 BEGIN {
6495                                         IGNORECASE=1
6496                                         position=""
6497                                         speed=""
6498                                         multisession=""
6499                                         mcn=""
6500                                         audio=""
6501                                         cdr=""
6502                                         cdrw=""
6503                                         dvd=""
6504                                         dvdr=""
6505                                         dvdram=""
6506                                 }
6507                                 # first get the position of the device name from top field
6508                                 # we will use this to get all the other data for that column
6509                                 /drive name:/ {
6510                                         for ( position=3; position <= NF; position++ ) {
6511                                                 if ( $position == diskId ) {
6512                                                         break
6513                                                 }
6514                                         }
6515                                 }
6516                                 /drive speed:/ {
6517                                         speed = $position
6518                                 }
6519                                 /Can read multisession:/ {
6520                                         multisession=$( position + 1 )
6521                                 }
6522                                 /Can read MCN:/ {
6523                                         mcn=$( position + 1 )
6524                                 }
6525                                 /Can play audio:/ {
6526                                         audio=$( position + 1 )
6527                                 }
6528                                 /Can write CD-R:/ {
6529                                         cdr=$( position + 1 )
6530                                 }
6531                                 /Can write CD-RW:/ {
6532                                         cdrw=$( position + 1 )
6533                                 }
6534                                 /Can read DVD:/ {
6535                                         dvd=$( position + 1 )
6536                                 }
6537                                 /Can write DVD-R:/ {
6538                                         dvdr=$( position + 1 )
6539                                 }
6540                                 /Can write DVD-RAM:/ {
6541                                         dvdram=$( position + 1 )
6542                                 }
6543                                 END {
6544                                         print speed "," multisession "," mcn "," audio "," cdr "," cdrw "," dvd "," dvdr "," dvdram
6545                                 }
6546                                 ' <<< "$proc_cdrom" )
6547                         fi
6548                         item_string="$item_string,$vendor,$model,$rev_number,$proc_info_string,$state"
6549                         echo $item_string
6550                 done \
6551                 ) )
6552                 IFS="$ORIGINAL_IFS"
6553         fi
6554         temp_array=${A_OPTICAL_DRIVE_DATA[@]}
6555         log_function_data "A_OPTICAL_DRIVE_DATA: $temp_array"
6556         eval $LOGFE
6557 }
6558
6559 get_partition_data()
6560 {
6561         eval $LOGFS
6562         
6563         local a_partition_working='' dev_item='' temp_array='' dev_working_item='' 
6564         local swap_data='' df_string='' main_partition_data='' df_test='' fs_type=''
6565         local mount_data='' dev_bsd_item=''
6566         #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660'
6567         # df doesn't seem to work in script with variables like at the command line
6568         # added devfs linprocfs sysfs fdescfs which show on debian kfreebsd kernel output
6569         if [[ -z $BSD_TYPE ]];then
6570                 swap_data="$( swapon -s 2>/dev/null )"
6571                 df_string='df -h -T -P --exclude-type=aufs --exclude-type=devfs --exclude-type=devtmpfs 
6572                 --exclude-type=fdescfs --exclude-type=iso9660 --exclude-type=linprocfs --exclude-type=procfs
6573                 --exclude-type=squashfs --exclude-type=sysfs --exclude-type=tmpfs --exclude-type=unionfs'
6574         else
6575                 swap_data="$( swapctl -l 2>/dev/null )"
6576                 # default size is 512, -H only for size in human readable format
6577                 # older bsds don't support -T, pain, so we'll use partial output there
6578                 df_test=$( df -H -T 2>/dev/null )
6579                 if [[ -n $df_test ]];then
6580                         df_string='df -H -T'
6581                 else
6582                         df_string='df -H'
6583                 fi
6584         fi
6585         main_partition_data="$( eval $df_string )"
6586         # set dev disk label/mapper/uuid data globals
6587         get_partition_dev_data 'label'
6588         get_partition_dev_data 'mapper'
6589         get_partition_dev_data 'uuid'
6590         
6591         log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data"
6592         
6593         # new kernels/df have rootfs and / repeated, creating two entries for the same partition
6594         # so check for two string endings of / then slice out the rootfs one, I could check for it
6595         # before slicing it out, but doing that would require the same action twice re code execution
6596         if [[ $( grep -cs '[[:space:]]/$' <<< "$main_partition_data" ) -gt 1 ]];then
6597                 main_partition_data="$( grep -vs '^rootfs' <<< "$main_partition_data" )"
6598         fi
6599         log_function_data 'raw' "main_partition_data_post_rootfs:\n$main_partition_data\n\nswap_data:\n$swap_data"
6600         IFS=$'\n'
6601         # sample line: /dev/sda2     ext3     15G  8.9G  4.9G  65% /home
6602         # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used
6603         ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if
6604         ## the first field is too long, it will occupy its own line, this way we are getting only the needed data
6605         A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk -v bsdType=$BSD_TYPE '
6606         BEGIN {
6607                 IGNORECASE=1
6608                 fileSystem=""
6609         }
6610         # this has to be nulled for every iteration so it does not retain value from last iteration
6611         devBase=""
6612         # skipping these file systems because bsds do not support df --exclude-type=<fstype>
6613         # note that using $1 to handle older bsd df, which do not support -T. This will not be reliable but we will see
6614         ( bsdType != "" ) {
6615                 # skip if non disk/partition, or if raid primary id, which will not have a / in it
6616                 if ( $1 ~ /^(aufs|devfs|devtmpfs|fdescfs|iso9660|linprocfs|procfs|squashfs|sysfs|tmpfs|type|unionfs)$/ || 
6617                 $1 ~ /^([^\/]+)$/ ) {
6618                         # note use next, not getline or it does not work right
6619                         next 
6620                 }
6621         }
6622         # this is required because below we are subtracting from NF, so it has to be > 5
6623         # the real issue is long file system names that force the wrap of df output: //fileserver/main
6624         # but we still need to handle more dynamically long space containing file names, but later.
6625         # Using df -P should fix this, ie, no wrapping of line lines, but leaving this for now
6626         ( NF < 6 ) && ( $0 !~ /[0-9]+%/ ) {
6627                 # set the dev location here for cases of wrapped output
6628                 if ( NF == 1 ) {
6629                         devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6630                 }
6631                 getline
6632         }
6633         
6634         # next set devBase if it didn not get set above here
6635         ( devBase == "" ) && ( $1 ~ /^\/dev\/|:\/|\/\// ) {
6636                 devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6637         }
6638         # this handles zfs type devices/partitions, which do not start with / but contain /
6639         ( bsdType != "" && devBase == "" && $1 ~ /^[^\/]+\/.+/ ) {
6640                 devBase=gensub( /^([^\/]+\/)([^\/]+)$/, "non-dev-\\1\\2", 1, $1 )
6641         }
6642         # this handles yet another fredforfaen special case where a mounted drive
6643         # has the search string in its name
6644         $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ {
6645                 # note, older df in bsd do not have file system column
6646                 if ( NF == "7" && $(NF - 1) ~ /[0-9]+%/ ) {
6647                         fileSystem=$(NF - 5)
6648                 }
6649                 else {
6650                         fileSystem=""
6651                 }
6652                 print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," fileSystem "," devBase 
6653         }
6654         # skip all these, including the first, header line. Use the --exclude-type
6655         # to handle new filesystems types we do not want listed here
6656         $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ {
6657                 # this is to avoid file systems with spaces in their names, that will make
6658                 # the test show the wrong data in each of the fields, if no x%, then do not use
6659                 # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name
6660                 if ( $(NF - 1) ~ /[0-9]+%/ ) {
6661                         # note, older df in bsd do not have file system column
6662                         if ( NF == "7" ) {
6663                                 fileSystem=$(NF - 5)
6664                         }
6665                         else {
6666                                 fileSystem=""
6667                         }
6668                         print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," fileSystem "," devBase 
6669                 }
6670                 # these two cases construct the space containing name
6671                 else if ( $(NF - 2) ~ /[0-9]+%/ ) {
6672                         # note, older df in bsd do not have file system column
6673                         if ( NF == "8" && $(NF - 6) !~ /^[0-9]+/ ) {
6674                                 fileSystem=$(NF - 6)
6675                         }
6676                         else {
6677                                 fileSystem=""
6678                         }
6679                         print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," fileSystem "," devBase
6680                 }
6681                 else if ( $(NF - 3) ~ /[0-9]+%/ ) {
6682                         # note, older df in bsd do not have file system column
6683                         if ( NF == "9" && $(NF - 7) !~ /^[0-9]+/ ) {
6684                                 fileSystem=$(NF - 7)
6685                         }
6686                         else {
6687                                 fileSystem=""
6688                         }
6689                         print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," fileSystem "," devBase 
6690                 }
6691         }' )
6692         
6693         # now add the swap partition data, don't want to show swap files, just partitions,
6694         # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this
6695         # data, it's the same exact output as swapon -s
6696         $( echo "$swap_data" | gawk -v bsdType=$BSD_TYPE '
6697         BEGIN {
6698                 swapCounter = 1
6699                 usedHolder=""
6700                 sizeHolder=""
6701         }
6702         /^\/dev/ {
6703                 if ( bsdType == "" ) {
6704                         usedHolder=$4
6705                         sizeHolder=$3
6706                 }
6707                 else {
6708                         usedHolder=$3
6709                         sizeHolder=$2
6710                 }
6711                 size = sprintf( "%.2f", sizeHolder*1024/1000**3 )
6712                 devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6713                 used = sprintf( "%.2f", usedHolder*1024/1000**3 )
6714                 percentUsed = sprintf( "%.0f", ( usedHolder/sizeHolder )*100 )
6715                 print "swap-" swapCounter "," size "GB," used "GB," percentUsed "%,main," "swap," devBase
6716                 swapCounter = ++swapCounter
6717         }' ) )
6718         IFS="$ORIGINAL_IFS"
6719         
6720         temp_array=${A_PARTITION_DATA[@]}
6721         # echo $temp_array
6722         log_function_data "1: A_PARTITION_DATA:\n$temp_array"
6723         
6724         # we'll use this for older systems where no filesystem type is shown in df
6725         if [[ $BSD_TYPE == 'bsd' ]];then
6726                 mount_data="$( mount )"
6727         fi
6728         # now we'll handle some fringe cases where irregular df -hT output shows /dev/disk/.. instead of 
6729         # /dev/h|sdxy type data for column 1, . A_PARTITION_DATA[6]
6730         # Here we just search for the uuid/label and then grab the end of the line to get the right dev item.
6731         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6732         do
6733                 IFS=","
6734                 a_partition_working=( ${A_PARTITION_DATA[i]} )
6735                 IFS="$ORIGINAL_IFS"
6736                 
6737                 dev_item=${a_partition_working[6]} # reset each loop
6738                 fs_type=${a_partition_working[5]}
6739                 # older bsds have df minus -T so can't get fs type easily, try using mount instead
6740                 if [[ $BSD_TYPE == 'bsd' && -z $fs_type && -n $dev_item ]];then
6741                         dev_bsd_item=$( sed -e 's/non-dev-//' -e 's|/|\\/|g' <<< "$dev_item" )
6742                         fs_type=$( gawk -F '(' '
6743                         /'$dev_bsd_item'/ {
6744                                 # slice out everything after / plus the first comma
6745                                 sub( /,.*/, "", $2 )
6746                                 print $2
6747                                 exit
6748                         }' <<< "$mount_data" )
6749                 fi
6750                 # note: for swap this will already be set
6751                 if [[ -n $( grep -E '(by-uuid|by-label)' <<< $dev_item ) ]];then
6752                         dev_working_item=$( basename $dev_item )
6753                         if [[ -n $DEV_DISK_UUID ]];then
6754                                 dev_item=$( echo "$DEV_DISK_UUID" | gawk '
6755                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
6756                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6757                                                 print item
6758                                                 exit
6759                                         }' )
6760                         fi
6761                         # if we didn't find anything for uuid try label
6762                         if [[ -z $dev_item && -n $DEV_DISK_LABEL ]];then
6763                                 dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
6764                                         $0 ~ /[ /t]'$dev_working_item'[ /t]/ {
6765                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6766                                                 print item
6767                                                 exit
6768                                         }' )
6769                         fi
6770                 elif [[ -n $( grep 'mapper/' <<< $dev_item ) ]];then
6771                         # get the mapper actual dev item
6772                         dev_item=$( get_dev_processed_item "$dev_item" )
6773                 fi
6774                 
6775                 if [[ -n $dev_item ]];then
6776                         # assemble everything we could get for dev/h/dx, label, and uuid
6777                         IFS=","
6778                         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
6779                         IFS="$ORIGINAL_IFS"
6780                 fi
6781         done
6782         temp_array=${A_PARTITION_DATA[@]}
6783         # echo $temp_array
6784         log_function_data "2: A_PARTITION_DATA:\n$temp_array"
6785         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
6786                 get_partition_data_advanced
6787         fi
6788         eval $LOGFE
6789 }
6790
6791 # first get the locations of the mount points for label/uuid detection
6792 get_partition_data_advanced()
6793 {
6794         eval $LOGFS
6795         local a_partition_working='' dev_partition_data=''
6796         local dev_item='' dev_label='' dev_uuid='' temp_array=''
6797         local mount_point=''
6798         # set dev disk label/mapper/uuid data globals
6799         get_partition_dev_data 'label'
6800         get_partition_dev_data 'mapper'
6801         get_partition_dev_data 'uuid'
6802
6803         if [[ $B_MOUNTS_FILE == 'true' ]];then
6804                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6805                 do
6806                         IFS=","
6807                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6808                         IFS="$ORIGINAL_IFS"
6809                         
6810                         # note: for swap this will already be set
6811                         if [[ -z ${a_partition_working[6]} ]];then
6812                                 
6813                                 mount_point=$( sed 's|/|\\/|g'  <<< ${a_partition_working[0]} )
6814                                 #echo mount_point $mount_point
6815                                 dev_partition_data=$( gawk '
6816                                 BEGIN {
6817                                         IGNORECASE = 1
6818                                         partition = ""
6819                                         partTemp = ""
6820                                 }
6821                                 # trying to handle space in name
6822 #                               gsub( /\\040/, " ", $0 )
6823                                 /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" {
6824                                         # initialize the variables
6825                                         label = ""
6826                                         uuid = ""
6827
6828                                         # slice out the /dev
6829                                         partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
6830                                         # label and uuid can occur for root, set partition to null now
6831                                         if ( partition ~ /by-label/ ) {
6832                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 )
6833                                                 partition = ""
6834                                         }
6835                                         if ( partition ~ /by-uuid/ ) {
6836                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 )
6837                                                 partition = ""
6838                                         }
6839
6840                                         # handle /dev/root for / id
6841                                         if ( partition == "root" ) {
6842                                                 # if this works, great, otherwise, just set this to null values
6843                                                 partTemp="'$( readlink /dev/root 2>/dev/null )'"
6844                                                 if ( partTemp != "" ) {
6845                                                         if ( partTemp ~ /[hsv]d[a-z][0-9]{1,2}/ ) {
6846                                                                 partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp )
6847                                                         }
6848                                                         else if ( partTemp ~ /by-uuid/ ) {
6849                                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp )
6850                                                                 partition="" # set null to let real location get discovered
6851                                                         }
6852                                                         else if ( partTemp ~ /by-label/ ) {
6853                                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp )
6854                                                                 partition="" # set null to let real location get discovered
6855                                                         }
6856                                                 }
6857                                                 else {
6858                                                         partition = ""
6859                                                         label = ""
6860                                                         uuid = ""
6861                                                 }
6862                                         }
6863                                         print partition "," label "," uuid
6864                                         exit
6865                                 }'      $FILE_MOUNTS )
6866
6867                                 # assemble everything we could get for dev/h/dx, label, and uuid
6868                                 IFS=","
6869                                 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
6870                                 IFS="$ORIGINAL_IFS"
6871                         fi
6872                         ## now we're ready to proceed filling in the data
6873                         IFS=","
6874                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6875                         IFS="$ORIGINAL_IFS"
6876                         # get the mapper actual dev item first, in case it's mapped
6877                         dev_item=$( get_dev_processed_item "${a_partition_working[6]}" )
6878                         # make sure not to slice off rest if it's a network mounted file system
6879                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
6880                                 dev_item=$( basename $dev_item ) ## needed to avoid error in case name still has / in it
6881                         fi
6882                         dev_label=${a_partition_working[7]}
6883                         dev_uuid=${a_partition_working[8]}
6884                         # then if dev data/uuid is incomplete, try to get missing piece
6885                         # it's more likely we'll get a uuid than a label. But this should get the
6886                         # dev item set no matter what, so then we can get the rest of any missing data
6887                         # first we'll get the dev_item if it's missing
6888                         if [[ -z $dev_item ]];then
6889                                 if [[ -n $DEV_DISK_UUID && -n $dev_uuid ]];then
6890                                         dev_item=$( echo "$DEV_DISK_UUID" | gawk '
6891                                                 $0 ~ /[ \t]'$dev_uuid'[ \t]/ {
6892                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6893                                                         print item
6894                                                         exit
6895                                                 }' )
6896                                 elif [[ -n $DEV_DISK_LABEL && -n $dev_label ]];then
6897                                         dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
6898                                                 # first we need to change space x20 in by-label back to a real space
6899                                                 #gsub( /x20/, " ", $0 )
6900                                                 # then we can see if the string is there
6901                                                 $0 ~ /[ \t]'$dev_label'[ \t]/ {
6902                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
6903                                                         print item
6904                                                         exit
6905                                                 }' )
6906                                 fi
6907                         fi
6908                         
6909                         # this can trigger all kinds of weird errors if it is a non /dev path, like: remote:/machine/name
6910                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
6911                                 if [[ -n $DEV_DISK_UUID && -z $dev_uuid ]];then
6912                                         dev_uuid=$( echo "$DEV_DISK_UUID" | gawk  '
6913                                         /'$dev_item'$/ {
6914                                                 print $(NF - 2)
6915                                                 exit
6916                                         }' )
6917                                 fi
6918                                 if [[ -n $DEV_DISK_LABEL && -z $dev_label ]];then
6919                                         dev_label=$( echo "$DEV_DISK_LABEL" | gawk '
6920                                         /'$dev_item'$/ {
6921                                                 print $(NF - 2)
6922                                                 exit
6923                                         }' )
6924                                 fi
6925                         fi
6926
6927                         # assemble everything we could get for dev/h/dx, label, and uuid
6928                         IFS=","
6929                         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
6930                         IFS="$ORIGINAL_IFS"
6931                 done
6932                 log_function_data 'cat' "$FILE_MOUNTS"
6933         else
6934                 if [[ $BSD_TYPE == 'bsd' ]];then
6935                         get_partition_data_advanced_bsd
6936                 fi
6937         fi
6938         temp_array=${A_PARTITION_DATA[@]}
6939         # echo $temp_array
6940         log_function_data "3-advanced: A_PARTITION_DATA:\n$temp_array"
6941         eval $LOGFE
6942 }
6943
6944 get_partition_data_advanced_bsd()
6945 {
6946         eval $LOGFS
6947         local gpart_data="$( gpart list 2>/dev/null )"
6948         local a_partition_working='' label_uuid='' dev_item=''
6949         
6950         if [[ -n $gpart_data ]];then
6951                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
6952                 do
6953                         IFS=","
6954                         a_partition_working=( ${A_PARTITION_DATA[i]} )
6955                         IFS="$ORIGINAL_IFS"
6956                         # no need to use the rest of the name if it's not a straight /dev/item
6957                         dev_item=$( basename ${a_partition_working[6]} )
6958                         
6959                         label_uuid=$( gawk -F ':' '
6960                         BEGIN {
6961                                 IGNORECASE=1
6962                                 label=""
6963                                 uuid=""
6964                         }
6965                         /^[0-9]+\.[[:space:]]*Name.*'$dev_item'/ {
6966                                 while ( getline && $1 !~ /^[0-9]+\.[[:space:]]*Name/ ) {
6967                                         if ( $1 ~ /rawuuid/ ) {
6968                                                 gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
6969                                                 uuid=$2
6970                                         }
6971                                         if ( $1 ~ /label/ ) {
6972                                                 gsub(/^[[:space:]]+|[[:space:]]+$|none|\(null\)/,"",$2)
6973                                                 label=$2
6974                                         }
6975                                 }
6976                                 print label","uuid
6977                                 exit
6978                         }' <<< "$gpart_data" )
6979
6980                         # assemble everything we could get for dev/h/dx, label, and uuid
6981                         IFS=","
6982                         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
6983                         IFS="$ORIGINAL_IFS"
6984                 done
6985         fi
6986         eval $LOGFE
6987 }
6988
6989 # args: $1 - uuid/label/id/mapper
6990 get_partition_dev_data()
6991 {
6992         eval $LOGFS
6993         
6994         # only run these tests once per directory to avoid excessive queries to fs
6995         case $1 in
6996                 id)
6997                         if [[ $B_ID_SET != 'true' ]];then
6998                                 if [[ -d /dev/disk/by-id ]];then
6999                                         DEV_DISK_ID="$( ls -l /dev/disk/by-id )"
7000                                 fi
7001                                 B_ID_SET='true'
7002                         fi
7003                         ;;
7004                 label)
7005                         if [[ $B_LABEL_SET != 'true' ]];then
7006                                 if [[ -d /dev/disk/by-label ]];then
7007                                         DEV_DISK_LABEL="$( ls -l /dev/disk/by-label )"
7008                                 fi
7009                                 B_LABEL_SET='true'
7010                         fi
7011                         ;;
7012                 mapper)
7013                         if [[ $B_MAPPER_SET != 'true' ]];then
7014                                 if [[ -d /dev/mapper ]];then
7015                                         DEV_DISK_MAPPER="$( ls -l /dev/mapper )"
7016                                 fi
7017                                 B_MAPPER_SET='true'
7018                         fi
7019                         ;;
7020                 uuid)
7021                         if [[ $B_UUID_SET != 'true' ]];then
7022                                 if [[ -d /dev/disk/by-uuid ]];then
7023                                         DEV_DISK_UUID="$( ls -l /dev/disk/by-uuid )"
7024                                 fi
7025                                 B_UUID_SET='true'
7026                         fi
7027                         ;;
7028                 
7029         esac
7030         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"
7031         # debugging section, uncomment to insert user data
7032 #       DEV_DISK_LABEL='
7033 #
7034 # '
7035 # DEV_DISK_UUID='
7036 #
7037 # '
7038 # DEV_DISK_MAPPER='
7039 #
7040 # '
7041         eval $LOGFE
7042 }
7043
7044 # args: $1 - dev item, check for mapper, then get actual dev item if mapped
7045 # eg: lrwxrwxrwx 1 root root       7 Sep 26 15:10 truecrypt1 -> ../dm-2 
7046 get_dev_processed_item()
7047 {
7048         eval $LOGFS
7049         
7050         local dev_item=$1 dev_return=''
7051         
7052         if [[ -n $DEV_DISK_MAPPER && -n $( grep -is 'mapper/' <<< $dev_item ) ]];then
7053                 dev_return=$( echo "$DEV_DISK_MAPPER" | gawk '
7054                 $( NF - 2 ) ~ /^'$( basename $dev_item )'$/ {
7055                         item=gensub( /..\/(.+)/, "\\1", 1, $NF )
7056                         print item
7057                 }' )
7058         fi
7059         if [[ -z $dev_return ]];then
7060                 dev_return=$dev_item
7061         fi
7062         
7063         echo $dev_return
7064
7065         eval $LOGFE
7066 }
7067
7068 get_patch_version_string()
7069 {
7070         local patch_version_number=$( sed 's/^[0]*//' <<< $SCRIPT_PATCH_NUMBER )
7071         
7072         if [[ -n $patch_version_number ]];then
7073                 patch_version_number="-$patch_version_number"
7074                 # for cases where it was for example: 00-bsd cleaned to --bsd trim out one -
7075                 if [[ -n $( grep '\--' <<< $patch_version_number ) ]];then
7076                         patch_version_number=$( sed 's/--/-/' <<< $patch_version_number )
7077                 fi
7078         fi
7079         echo $patch_version_number
7080 }
7081
7082 get_pciconf_data()
7083 {
7084         eval $LOGFS
7085         
7086         local pciconf_data='' temp_array=''
7087         
7088         if [[ $B_PCICONF == 'true' ]];then
7089                 pciconf_data="$( pciconf -lv 2>/dev/null )"
7090                 if [[ -n $pciconf_data ]];then
7091                         pciconf_data=$( gawk '
7092                         BEGIN {
7093                                 IGNORECASE=1
7094                         }
7095                         {
7096                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
7097                                         gsub(/[[:space:]]+=[[:space:]]+/, "=",$0)
7098                                         gsub(/^[[:space:]]+|'"'"'|\"|,/, "", $0)
7099                                         gsub(/=0x/,"=",$0)
7100                                         # line=gensub(/.*[[:space:]]+(class=[^[:space:]]*|card=[^[:space:]]*)|chip=[^[:space:]]*|rev=[^[:space:]]*|hdr=[^[:space:]]*).*/,"\n\\1","g",$0)
7101                                         line=gensub(/(.*@.*)/,"\n\\1",$0)
7102                                         print line
7103                         }' <<< "$pciconf_data" )
7104                         # create empty last line with this spacing trick
7105                         pciconf_data="$pciconf_data
7106
7107 EOF"
7108                         # echo "$pciconf_data"
7109                         # now insert into arrays
7110                         IFS=$'\n'
7111                         A_PCICONF_DATA=( $( gawk '
7112                         BEGIN {
7113                                 fullLine=""
7114                                 driver=""
7115                                 vendor=""
7116                                 device=""
7117                                 class=""
7118                                 chipId=""
7119                                 pciId=""
7120                                 itemData=""
7121                                 IGNORECASE=1
7122                         }
7123                         /^.*@/ {
7124                                 pciId=""
7125                                 vendor=""
7126                                 class=""
7127                                 driver=""
7128                                 device=""
7129                                 chipId=""
7130                                 itemData=$1
7131                                 
7132                                 driver=gensub(/^([^@]+)@.*/, "\\1", itemData )
7133                                 pciId=gensub(/^.*@pci([0-9\.:]+).*/, "\\1", itemData )
7134                                 sub(/:$/, "", pciId)
7135                                 itemData=$4
7136                                 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 )
7137                                 if ( $2 == "class=020000" ) {
7138                                         class="network"
7139                                 }
7140                                 else if ( $2 == "class=030000" ) {
7141                                         class="display"
7142                                 }
7143                                 else if ( $2 == "class=040300" ) {
7144                                         class="audio"
7145                                 }
7146                                 
7147                                 while ( getline && $1 !~ /^$/ ) {
7148                                         if ( $1 ~ /^vendor/ ) {
7149                                                 sub(/^vendor=/, "", $1 )
7150                                                 vendor=$0
7151                                         }
7152                                         else if ( $1 ~ /^device/ ) {
7153                                                 sub(/^device=/, "", $1 )
7154                                                 device=$0
7155                                         }
7156                                         else if ( $1 ~ /^class=/ && class == "" ) {
7157                                                 sub(/^class=/, "", $1)
7158                                                 class=$0
7159                                         }
7160                                 }
7161                                 if ( device == "" ) {
7162                                         device=vendor
7163                                 }
7164                                 
7165                                 fullLine=class "," device "," vendor "," driver "," pciId "," chipId
7166                                 print fullLine
7167                         
7168                         }' <<< "$pciconf_data" ))
7169                         IFS="$ORIGINAL_IFS"
7170                 fi
7171         else
7172                 A_PCICONF_DATA='pciconf-not-installed'
7173         fi
7174         B_PCICONF_SET='true'
7175         temp_array=${A_PCICONF_DATA[@]}
7176         log_function_data "$temp_array"
7177         log_function_data "$pciconf_data"
7178         eval $LOGFE
7179 }
7180
7181 # packs standard card arrays using the pciconf stuff
7182 # args: $1 - audio/network/display - matches first item in A_PCICONF_DATA arrays
7183 get_pciconf_card_data()
7184 {
7185         eval $LOGFS
7186         local a_temp='' array_string='' j=0 device_string=''
7187         local ip_tool_command=$( type -p ifconfig )
7188         local mac='' state='' speed='' duplex='' network_string=''
7189         
7190         for (( i=0;i<${#A_PCICONF_DATA[@]};i++ ))
7191         do
7192                 IFS=','
7193                 a_temp=( ${A_PCICONF_DATA[i]} )
7194                 IFS="$ORIGINAL_IFS"
7195                 
7196                 if [[ ${a_temp[0]} == $1 ]];then
7197                         # don't print the vendor if it's already in the device name
7198                         if [[ -z $( grep -i "${a_temp[2]}" <<< "${a_temp[1]}" ) ]];then
7199                                 device_string="${a_temp[2]} ${a_temp[1]}"
7200                         else
7201                                 device_string=${a_temp[1]}
7202                         fi
7203                         case $1 in
7204                                 audio)
7205                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},,${a_temp[5]}"
7206                                         A_AUDIO_DATA[j]=$array_string
7207                                         ;;
7208                                 display)
7209                                         array_string="$device_string,${a_temp[4]},${a_temp[5]}"
7210                                         A_GRAPHICS_CARD_DATA[j]=$array_string
7211                                         ;;
7212                                 network)
7213                                         if [[ -n $ip_tool_command && -n ${a_temp[3]} ]];then
7214                                                 network_string=$(       $ip_tool_command ${a_temp[3]} | gawk '
7215                                                 BEGIN {
7216                                                         IGNORECASE=1
7217                                                         mac=""
7218                                                         state=""
7219                                                         speed=""
7220                                                         duplex=""
7221                                                 }
7222                                                 /^[[:space:]]*ether/ {
7223                                                         mac = $2
7224                                                 }
7225                                                 /^[[:space:]]*media/ {
7226                                                         if ( $0 ~ /<.*>/ ) {
7227                                                                 duplex=gensub(/.*<([^>]+)>.*/,"\\1",$0)
7228                                                         }
7229                                                         if ( $0 ~ /\(.*\)/ ) {
7230                                                                 speed=gensub(/.*\(([^<[:space:]]+).*\).*/,"\\1",$0)
7231                                                         }
7232                                                 }
7233                                                 /^[[:space:]]*status/ {
7234                                                         sub(/.*status[:]?[[:space:]]*/,"", $0)
7235                                                         state=$0
7236                                                 }
7237                                                 END {
7238                                                         print state "~" speed "~" mac "~" duplex
7239                                                 }')
7240                                         fi
7241                                         if [[ -n $network_string ]];then
7242                                                 mac=$( cut -d '~' -f 3 <<< $network_string )
7243                                                 state=$( cut -d '~' -f 1 <<< $network_string )
7244                                                 speed=$( cut -d '~' -f 2 <<< $network_string )
7245                                                 duplex=$( cut -d '~' -f 4 <<< $network_string )
7246                                         fi
7247                                         array_string="$device_string,${a_temp[3]},,,${a_temp[4]},${a_temp[3]},$state,$speed,$duplex,$mac,${a_temp[5]}"
7248                                         A_NETWORK_DATA[j]=$array_string
7249                                         ;;
7250                         esac
7251                         ((j++))
7252                 fi
7253         done
7254         
7255         eval $LOGFE
7256 }
7257
7258 # args: $1 - type cpu/mem 
7259 get_ps_tcm_data()
7260 {
7261         eval $LOGFS
7262         local array_length='' reorder_temp='' i=0 head_tail='' sort_type='' ps_data=''
7263         
7264         # bummer, have to make it more complex here because of reverse sort
7265         # orders in output, pesky lack of support of +rss in old systems
7266         case $1 in
7267                 mem)
7268                         if [[ $BSD_TYPE != 'bsd' ]];then
7269                                 sort_type='ps aux --sort -rss'
7270                                 head_tail='head'
7271                         else
7272                                 sort_type='ps aux -m'
7273                                 head_tail='head'
7274                         fi
7275                         ;;
7276                 cpu)
7277                         if [[ $BSD_TYPE != 'bsd' ]];then
7278                                 sort_type='ps aux --sort %cpu'
7279                                 head_tail='tail'
7280                         else
7281                                 sort_type='ps aux -r'
7282                                 head_tail='head'
7283                         fi
7284                         ;;
7285         esac
7286         
7287         # throttle potential irc abuse
7288         if [[ $B_RUNNING_IN_SHELL != 'true' && $PS_COUNT -gt 5 ]];then
7289                 PS_THROTTLED=$PS_COUNT
7290                 PS_COUNT=5
7291         fi
7292         # use eval here to avoid glitches with -
7293         ps_data="$( eval $sort_type )"
7294
7295         IFS=$'\n'
7296         # note that inxi can use a lot of cpu, and can actually show up here as the script runs
7297         A_PS_DATA=( $( echo "$ps_data" | grep -Ev "($SCRIPT_NAME|%CPU|[[:space:]]ps[[:space:]])" | $head_tail -n $PS_COUNT | gawk '
7298         BEGIN {
7299                 IGNORECASE=1
7300                 appName=""
7301                 appPath=""
7302                 appStarterName=""
7303                 appStarterPath=""
7304                 cpu=""
7305                 mem=""
7306                 pid=""
7307                 user=""
7308                 rss=""
7309         }
7310         {
7311                 cpu=$3
7312                 mem=$4
7313                 pid=$2
7314                 user=$1
7315                 rss=sprintf( "%.2f", $6/1024 )
7316                 # have to get rid of [,],(,) eg: [lockd] which break the printout function compare in bash
7317                 gsub(/\[|\]|\(|\)/,"~", $0 )
7318                 if ( $12 ~ /^\// ){
7319                         appStarterPath=$11
7320                         appPath=$12
7321                 }
7322                 else {
7323                         appStarterPath=$11
7324                         appPath=$11
7325                 }
7326                 appStarterName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appStarterPath )
7327                 appName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appPath )
7328                 print appName "," appPath "," appStarterName "," appStarterPath "," cpu "," mem "," pid "," rss "," user
7329         }
7330         ' ) )
7331         # make the array ordered highest to lowest so output looks the way we expect it to
7332         # this isn't necessary for -rss, and we can't make %cpu ordered the other way, so
7333         # need to reverse it here. -rss is used because on older systems +rss is not supported
7334         if [[ $1 == 'cpu' && $BSD_TYPE != 'bsd' ]];then
7335                 array_length=${#A_PS_DATA[@]}; 
7336                 while (( $i < $array_length/2 ))
7337                 do 
7338                         reorder_temp=${A_PS_DATA[i]}f
7339                         A_PS_DATA[i]=${A_PS_DATA[$array_length-$i-1]}
7340                         A_PS_DATA[$array_length-$i-1]=$reorder_temp
7341                         (( i++ ))
7342                 done 
7343         fi
7344
7345         IFS="$ORIGINAL_IFS"
7346         
7347 #       echo ${A_PS_DATA[@]}
7348         eval $LOGFE
7349 }
7350
7351 # mdstat syntax information: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
7352 # note that this does NOT use either Disk or Partition information for now, ie, there
7353 # is no connection between the data types, but the output should still be consistent
7354 get_raid_data()
7355 {
7356         eval $LOGFS
7357         
7358         local mdstat=''
7359                 
7360         if [[ $B_MDSTAT_FILE == 'true' ]];then
7361                 mdstat="$( cat $FILE_MDSTAT 2>/dev/null )"
7362         fi
7363         
7364         if [[ -n $mdstat ]];then
7365                 # need to make sure there's always a newline in front of each record type, and
7366                 # also correct possible weird formats for the output from older kernels etc.
7367                 mdstat="$( sed -e 's/^md/\nmd/' -e 's/^unused[[:space:]]/\nunused /' \
7368                 -e 's/read_ahead/\nread_ahead/' -e 's/^resync=/\nresync=/' -e 's/^Event/\nEvent/' \
7369                 -e 's/^[[:space:]]*$//' -e 's/[[:space:]]read_ahead/\nread_ahead/' <<< "$mdstat" )"
7370                 # some fringe cases do not end as expected, so need to add newlines plus EOF to make sure while loop doesn't spin
7371                 mdstat=$( echo -e "$mdstat\n\nEOF" )
7372
7373                 IFS=$'\n'
7374                 A_RAID_DATA=( $(
7375                 gawk '
7376                 BEGIN {
7377                         IGNORECASE=1
7378                         RS="\n"
7379                 }
7380                 
7381                 /^personalities/ {
7382                         KernelRaidSupport = gensub(/personalities[[:space:]]*:[[:space:]]*(.*)/, "\\1", 1, $0)
7383                         # clean off the brackets
7384                         gsub(/[\[\]]/,"",KernelRaidSupport)
7385                         print "KernelRaidSupport," KernelRaidSupport
7386                 }
7387                 /^read_ahead/ {
7388                         ReadAhead=gensub(/read_ahead (.*)/, "\\1", 1 )
7389                         print "ReadAhead," ReadAhead
7390                 }
7391                 /^Event:/ {
7392                         print "raidEvent," $NF
7393                 }
7394                 # print logic will search for this value and use it to print out the unused devices data
7395                 /^unused devices/ {
7396                         unusedDevices = gensub(/^unused devices:[[:space:]][<]?([^>]*)[>]?.*/, "\\1", 1, $0)
7397                         print "UnusedDevices," unusedDevices
7398                 }
7399                 
7400                 /^md/ {
7401                         # reset for each record loop through
7402                         deviceState = ""
7403                         bitmapValues = ""
7404                         blocks = ""
7405                         chunkSize = ""
7406                         components = ""
7407                         device = ""
7408                         deviceReport = ""
7409                         finishTime = ""
7410                         recoverSpeed = ""
7411                         recoveryProgressBar = ""
7412                         recoveryPercent = ""
7413                         raidLevel = ""
7414                         sectorsRecovered = ""
7415                         separator = ""
7416                         superBlock = ""
7417                         uData = ""
7418                         
7419                         while ( !/^[[:space:]]*$/  ) {
7420                                 gsub(/,/, " ", $0 )
7421                                 gsub(/[[:space:]]+/, " ", $0 )
7422                                 if ( $0 ~ /^md/ ) {
7423                                         device = gensub(/(md.*)[[:space:]]?:/, "\\1", "1", $1 )
7424                                 }
7425                                 if ( $0 ~ /mirror|raid[0-9]+/ ) {
7426                                         raidLevel = gensub(/(.*)raid([0-9]+)(.*)/, "\\2", "g", $0 )
7427                                 }
7428                                 if ( $0 ~ /(active \(auto-read-only\)|active|inactive)/ ) {
7429                                         deviceState = gensub(/(.*) (active \(auto-read-only\)|active|inactive) (.*)/, "\\2", "1", $0 )
7430                                 }
7431                                 # gawk will not return all the components using gensub, only last one
7432                                 separator = ""
7433                                 for ( i=3; i<=NF; i++ ) {
7434                                         if ( $i ~ /[hs]d[a-z][0-9]*(\[[0-9]+\])?(\([SF]\))?/ ) {
7435                                                 components = components separator $i
7436                                                 separator=" "
7437                                         }
7438                                 }
7439                                 if ( $0 ~ /blocks/ ) {
7440                                         blocks = gensub(/(.*[[:space:]]+)?([0-9]+)[[:space:]]blocks.*/, "\\2", "1", $0)
7441                                 }
7442                                 if ( $0 ~ /super[[:space:]][0-9\.]+/ ) {
7443                                         superBlock = gensub(/.*[[:space:]]super[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
7444                                 }
7445                                 if ( $0 ~ /algorithm[[:space:]][0-9\.]+/ ) {
7446                                         algorithm = gensub(/.*[[:space:]]algorithm[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
7447                                 }
7448                                 if ( $0 ~ /\[[0-9]+\/[0-9]+\]/ ) {
7449                                         deviceReport = gensub(/.*[[:space:]]\[([0-9]+\/[0-9]+)\][[:space:]].*/, "\\1", "1", $0)
7450                                         uData = gensub(/.*[[:space:]]\[([U_]+)\]/, "\\1", "1", $0)
7451                                 }
7452                                 # need to avoid this:  bitmap: 0/10 pages [0KB], 16384KB chunk
7453                                 # while currently all the normal chunks are marked with k, not kb, this can change in the future
7454                                 if ( $0 ~ /[0-9]+[k] chunk/ && $0 !~ /bitmap/ ) {
7455                                         chunkSize = gensub(/(.*) ([0-9]+[k]) chunk.*/, "\\2", "1", $0)
7456                                 }
7457                                 if ( $0 ~ /^resync=/ ) {
7458                                         sub(/resync=/,"")
7459                                         print "resyncStatus," $0
7460                                 }
7461                                 if ( $0 ~ /\[[=]*>[\.]*\].*(resync|recovery)/ ) {
7462                                         recoveryProgressBar = gensub(/.*(\[[=]*>[\.]*\]).*/, "\\1",1,$0)
7463                                 }
7464                                 if ( $0 ~ / (resync|recovery)[[:space:]]*=/ ) {
7465                                         recoveryPercent = gensub(/.* (resync|recovery)[[:space:]]*=[[:space:]]*([0-9\.]+%).*/, "\\1~\\2", 1 )
7466                                         if ( $0 ~ /[[:space:]]\([0-9]+\/[0-9]+\)/ ) {
7467                                                 sectorsRecovered = gensub(/.* \(([0-9]+\/[0-9]+)\).*/, "\\1", 1, $0 )
7468                                         }
7469                                         if ( $0 ~ /finish[[:space:]]*=/ ) {
7470                                                 finishTime = gensub(/.* finish[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+) .*/, "\\1 \\2", 1, $0 )
7471                                         }
7472                                         if ( $0 ~ /speed[[:space:]]*=/ ) {
7473                                                 recoverSpeed = gensub(/.* speed[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+\/[a-z]+)/, "\\1 \\2", 1, $0 )
7474                                         }
7475                                 }
7476                                 if ( $0 ~ /bitmap/ ) {
7477                                         bitmapValues = gensub(/(.*[[:space:]])?bitmap:(.*)/, "\\2", 1, $0 )
7478                                 }
7479                                 
7480                                 getline
7481                         }
7482                         raidString = device "," deviceState "," raidLevel "," components "," deviceReport "," uData 
7483                         raidString = raidString "," blocks "," superBlock "," algorithm "," chunkSize "," bitmapValues
7484                         raidString = raidString "," recoveryProgressBar "," recoveryPercent "," sectorsRecovered "," finishTime "," recoverSpeed
7485                         
7486                         print raidString
7487                 }
7488                 ' <<< "$mdstat" ) )
7489                 IFS="$ORIGINAL_IFS"
7490         else
7491                 if [[ $BSD_TYPE == 'bsd' ]];then
7492                         get_raid_data_bsd
7493                 fi
7494         fi
7495         B_RAID_SET='true'
7496         temp_array=${A_RAID_DATA[@]}
7497         log_function_data "A_RAID_DATA: $temp_array"
7498 #       echo -e "A_RAID_DATA:\n${temp_array}"
7499         
7500         eval $LOGFE
7501 }
7502
7503 get_raid_data_bsd()
7504 {
7505         eval $LOGFS
7506         local zpool_path=$( type -p zpool 2>/dev/null )
7507         local zpool_data=''
7508         
7509         if [[ -n $zpool_path ]];then
7510                 B_BSD_RAID='true'
7511                 # bsd sed does not support inserting a true \n so use this trick
7512                 zpool_data="$( $zpool_path list -v | sed $SED_RX 's/^([^[:space:]])/\
7513 \1/' )"
7514 #               echo "$zpool_data"
7515                 IFS=$'\n'
7516                 A_RAID_DATA=( $(
7517                 gawk '
7518                 BEGIN {
7519                         raidString=""
7520                         separator=""
7521                         components=""
7522                         reportSize=""
7523                         blocksAvailable=""
7524                         chunkRaidAllocated=""
7525                 }
7526                 /SIZE.*ALLOC/ {
7527                         sub(/.*ALLOC.*/,"", $0)
7528                 }
7529                 /^[^[:space:]]/ {
7530                         components=""
7531                         separator=""
7532                         raidLevel=""
7533                         device=$1
7534                         deviceState=$7
7535                         reportSize=$2
7536                         blocksAvailable=$4
7537                         chunkRaidAllocated=$3
7538                         
7539                         # go to the next line now, this will probably need fixing later with weird data sets
7540                         getline
7541                         if ( $1 != "" ) {
7542                                 raidLevel="zfs " $1
7543                         }
7544                         
7545                         while ( getline && $1 !~ /^$/ ) {
7546                                 # print $1
7547                                 components = components separator $1
7548                                 separator=" "
7549                         }
7550
7551                         # print $1
7552                         raidString = device "," deviceState "," raidLevel "," components "," reportSize "," uData 
7553                         raidString = raidString "," blocksAvailable "," superBlock "," algorithm "," chunkRaidAllocated 
7554                         # none of these are used currently
7555                         raidString = raidString "," bitmapValues  "," recoveryProgressBar "," recoveryPercent 
7556                         raidString = raidString "," sectorsRecovered "," finishTime "," recoverSpeed
7557                         gsub(/~/,"",raidString)
7558                         print raidString
7559                 }' <<< "$zpool_data" ) )
7560                 IFS="$ORIGINAL_IFS"
7561                 get_raid_component_data_bsd
7562         fi
7563         eval $LOGFE
7564 }
7565
7566 # note, we've already tested for zpool so no further tests required
7567 get_raid_component_data_bsd()
7568 {
7569         eval $LOGFS
7570         local a_raid_data='' array_string='' component='' component_string='' 
7571         local zpool_status='' device='' separator='' component_status=''
7572         
7573         for (( i=0; i<${#A_RAID_DATA[@]}; i++))
7574         do
7575                 IFS=","
7576                 a_raid_data=( ${A_RAID_DATA[i]} )
7577                 IFS="$ORIGINAL_IFS"
7578                 separator=''
7579                 component_string=''
7580                 component_status=''
7581                 zpool_status=''
7582                 device=${a_raid_data[0]}
7583                 zpool_status="$( zpool status $device )"
7584                 # we will remove ONLINE for status and only use OFFLINE/DEGRADED as tests
7585                 # for print output display of issues with components
7586                 for component in ${a_raid_data[3]}
7587                 do
7588                         component_status=$( gawk '
7589                         BEGIN {
7590                                 IGNORECASE=1
7591                         }
7592                         $1 ~ /^'$component'$/ {
7593                                 sub( /ONLINE/, "", $2 )
7594                                 print "'$component'" $2
7595                                 exit
7596                         }' <<< "$zpool_status" )
7597                         component_string="$component_string$separator$component_status"
7598                         separator=' '
7599                 done
7600                 array_string="$device,${a_raid_data[1]},${a_raid_data[2]},$component_string,${a_raid_data[4]}"
7601                 array_string="$array_string,${a_raid_data[5]},${a_raid_data[6]},${a_raid_data[7]},${a_raid_data[8]}"
7602                 array_string="$array_string,${a_raid_data[9]},${a_raid_data[10]},${a_raid_data[11]},${a_raid_data[12]},"
7603                 array_string="$array_string${a_raid_data[13]},${a_raid_data[14]},${a_raid_data[15]}"
7604                 IFS=","
7605                 A_RAID_DATA[i]=$array_string
7606                 IFS="$ORIGINAL_IFS"
7607         done
7608         
7609         eval $LOGFE
7610 }
7611 # get_raid_data_bsd;exit
7612
7613 # Repos will be added as we get distro package manager data to create the repo data. 
7614 # This method will output the file name also, which is useful to create output that's 
7615 # neat and readable. Each line of the total number contains the following sections,
7616 # separated by a : for splitting in the print function
7617 # part one, repo type/string : part two, file name, if present, of info : part 3, repo data
7618 get_repo_data()
7619 {
7620         eval $LOGFS
7621         local repo_file='' repo_data_working='' repo_data_working2='' repo_line='' repo_files=''
7622         local repo_name=''
7623         local apt_file='/etc/apt/sources.list' yum_repo_dir='/etc/yum.repos.d/' yum_conf='/etc/yum.conf'
7624         local pacman_conf='/etc/pacman.conf' pacman_repo_dir='/etc/pacman.d/' pisi_dir='/etc/pisi/'
7625         local zypp_repo_dir='/etc/zypp/repos.d/' freebsd_conf='/etc/portsnap.conf'
7626         
7627         # apt - debian, buntus, also sometimes some yum/rpm repos may create apt repos here as well
7628         if [[ -f $apt_file || -d $apt_file.d ]];then
7629                 REPO_DATA="$( grep -Esv '(^[[:space:]]*$|^[[:space:]]*#)' $apt_file $apt_file.d/*.list | sed $SED_RX 's/^(.*)/apt sources:\1/' )"
7630         fi
7631         # yum - fedora, redhat, centos, etc. Note that rpmforge also may create apt sources
7632         # in /etc/apt/sources.list.d/. Therefore rather than trying to assume what package manager is
7633         # actually running, inxi will merely note the existence of each repo type for apt/yum. 
7634         # Also, in rpm, you can install apt-rpm for the apt-get command, so it's not good to check for
7635         # only the commands in terms of selecting which repos to show.
7636         if [[ -d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir ]];then
7637                 if [[ -d $yum_repo_dir || -f $yum_conf ]];then
7638                         # older redhats put their yum data in /etc/yum.conf
7639                         repo_files=$( ls $yum_repo_dir*.repo $yum_conf 2>/dev/null )
7640                         repo_name='yum'
7641                 elif [[ -d $zypp_repo_dir ]];then
7642                         repo_files=$( ls $zypp_repo_dir*.repo 2>/dev/null )
7643                         repo_name='zypp'
7644                 fi
7645                 if [[ -n $repo_files ]];then
7646                         for repo_file in $repo_files
7647                         do
7648                                 repo_data_working="$( gawk -v repoFile=$repo_file '
7649                                 # construct the string for the print function to work with, file name: data
7650                                 function print_line( fileName, repoId, repoUrl ){
7651                                         print "'$repo_name' sources:" fileName ":" repoId repoUrl
7652                                 }
7653                                 BEGIN {
7654                                         FS="\n"
7655                                         IGNORECASE=1
7656                                         enabledStatus=""
7657                                         repoTitle=""
7658                                         urlData=""
7659                                 }
7660                                 # this is a hack, assuming that each item has these fields listed, we collect the 3
7661                                 # items one by one, then when the url/enabled fields are set, we print it out and
7662                                 # reset the data. Not elegant but it works. Note that if enabled was not present
7663                                 # we assume it is enabled then, and print the line, reset the variables. This will
7664                                 # miss the last item, so it is printed if found in END
7665                                 /^\[.+\]/ {
7666                                         if ( urlData != "" && repoTitle != "" ){
7667                                                 print_line( repoFile, repoTitle, urlData )
7668                                                 enabledStatus=""
7669                                                 urlData=""
7670                                                 repoTitle=""
7671                                         }
7672                                         gsub( /\[|\]/, "", $1 ) # strip out the brackets
7673                                         repoTitle = $1 " ~ "
7674                                 }
7675                                 /^(mirrorlist|baseurl)/ {
7676                                         sub( /(mirrorlist|baseurl)[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
7677                                         urlData = $1
7678                                 }
7679                                 # note: enabled = 1. enabled = 0 means disabled
7680                                 /^enabled[[:space:]]*=/ {
7681                                         enabledStatus = $1
7682                                 }
7683                                 # print out the line if all 3 values are found, otherwise if a new
7684                                 # repoTitle is hit above, it will print out the line there instead
7685                                 { 
7686                                         if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
7687                                                 if ( enabledStatus !~ /enabled[[:space:]]*=[[:space:]]*0/ ){
7688                                                         print_line( repoFile, repoTitle, urlData )
7689                                                 }
7690                                                 enabledStatus=""
7691                                                 urlData=""
7692                                                 repoTitle=""
7693                                         }
7694                                 }
7695                                 END {
7696                                         # print the last one if there is data for it
7697                                         if ( urlData != ""  && repoTitle != "" ){
7698                                                 print_line( repoFile, repoTitle, urlData )
7699                                         }
7700                                 }
7701                                 ' $repo_file )"
7702                                 
7703                                 # then load the global for each file as it gets filled
7704                                 if [[ -n $repo_data_working ]];then
7705                                         if [[ -z $REPO_DATA ]];then
7706                                                 REPO_DATA="$repo_data_working"
7707                                         else
7708                                                 REPO_DATA="$REPO_DATA
7709 $repo_data_working"
7710                                         fi
7711                                         repo_data_working=''
7712                                 fi
7713                         done
7714                 fi
7715         # pacman - archlinux, going to assume that pisi and arch/pacman, etc don't have the above issue with apt/yum
7716         elif [[ -f $pacman_conf ]];then
7717                 # get list of mirror include files, trim white space off ends
7718                 repo_data_working="$( gawk '
7719                 BEGIN {
7720                         FS="="
7721                         IGNORECASE=1
7722                 }
7723                 /^[[:space:]]*Include/ {
7724                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
7725                         print $2
7726                 }
7727                 ' $pacman_conf )"
7728                 # sort into unique paths only, to be used to search for server = data
7729                 repo_data_working=$( sort -bu <<< "$repo_data_working" | uniq ) 
7730                 repo_data_working="$repo_data_working $pacman_conf"
7731                 for repo_file in $repo_data_working 
7732                 do
7733                         if [[ -f $repo_file ]];then
7734                                 # inserting a new line after each found / processed match
7735                                 repo_data_working2="$repo_data_working2$( gawk -v repoFile=$repo_file '
7736                                 BEGIN {
7737                                         FS="="
7738                                         IGNORECASE=1
7739                                 }
7740                                 /^[[:space:]]*Server/ {
7741                                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
7742                                         print "pacman repo servers:" repoFile ":" $2 "\\n"
7743                                 }
7744                                 ' $repo_file )"
7745                         else
7746                                 echo "Error: file listed in $pacman_conf does not exist - $repo_file"
7747                         fi
7748                 done
7749                 # execute line breaks
7750                 REPO_DATA="$( echo -e $repo_data_working2 )"
7751         # pisi - pardus
7752         elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
7753                 REPO_DATA="$( pisi list-repo )"
7754                 # now we need to create the structure: repo info: repo path
7755                 # we do that by looping through the lines of the output and then
7756                 # putting it back into the <data>:<url> format print repos expects to see
7757                 # note this structure in the data, so store first line and make start of line
7758                 # then when it's an http line, add it, and create the full line collection.
7759 # Pardus-2009.1 [Aktiv]
7760 #       http://packages.pardus.org.tr/pardus-2009.1/pisi-index.xml.bz2
7761 # Contrib [Aktiv]
7762 #       http://packages.pardus.org.tr/contrib-2009/pisi-index.xml.bz2
7763                 while read repo_line
7764                 do
7765                         repo_line=$( gawk '
7766                         {
7767                                 # need to dump leading/trailing spaces and clear out color codes for irc output
7768                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
7769 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
7770                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
7771                                 print $0
7772                         }' <<< $repo_line )
7773                         if [[ -n $( grep '://' <<< $repo_line ) ]];then
7774                                 repo_data_working="$repo_data_working:$repo_line\n"
7775                         else
7776                                 repo_data_working="${repo_data_working}pisi repo:$repo_line"
7777                         fi
7778                 done <<< "$REPO_DATA"
7779                 # echo and execute the line breaks inserted
7780                 REPO_DATA="$( echo -e $repo_data_working )"
7781         # Mandriva/Mageia using: urpmq
7782         elif [[ -n $( type -p urpmq ) ]];then
7783                 REPO_DATA="$( urpmq --list-media active --list-url )"
7784                 # now we need to create the structure: repo info: repo path
7785                 # we do that by looping through the lines of the output and then
7786                 # putting it back into the <data>:<url> format print repos expects to see
7787                 # note this structure in the data, so store first line and make start of line
7788                 # then when it's an http line, add it, and create the full line collection.
7789 # Contrib ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/release
7790 # Contrib Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/updates
7791 # Non-free ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/release
7792 # Non-free Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/updates
7793 # Nonfree Updates (Local19) /mnt/data/mirrors/mageia/distrib/cauldron/x86_64/media/nonfree/updates
7794                 while read repo_line
7795                 do
7796                         repo_line=$( gawk '
7797                         {
7798                                 # need to dump leading/trailing spaces and clear out color codes for irc output
7799                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
7800 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
7801                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
7802                                 print $0
7803                         }' <<< $repo_line )
7804                         # urpmq output is the same each line, repo name space repo url, can be:
7805                         # rsync://, ftp://, file://, http:// OR repo is locally mounted on FS in some cases
7806                         if [[ -n $( grep -E '(://|[[:space:]]/)' <<< $repo_line ) ]];then
7807                                 # cut out the repo first
7808                                 repo_data_working2=$( grep -Eo '([^[:space:]]+://|[[:space:]]/).*' <<< $repo_line )
7809                                 # then get the repo name string by slicing out the url string
7810                                 repo_name=$( sed "s|[[:space:]]*$repo_data_working2||" <<< $repo_line )
7811                                 repo_data_working="${repo_data_working}urpmq repo:$repo_name:$repo_data_working2\n"
7812                         fi
7813                 done <<< "$REPO_DATA"
7814                 # echo and execute the line breaks inserted
7815                 REPO_DATA="$( echo -e $repo_data_working )"
7816         elif [[ -f $freebsd_conf ]];then
7817                 REPO_DATA="$( gawk -F '=' -v repoFile=$freebsd_conf '
7818                 BEGIN {
7819                         IGNORECASE=1
7820                 }
7821                 /^SERVERNAME/ {
7822                         print "BSD ports servers:" repoFile ":" $2
7823                 }
7824                 ' $freebsd_conf )"
7825         fi
7826         eval $LOGFE
7827 }
7828
7829 get_runlevel_data()
7830 {
7831         eval $LOGFS
7832         local runlvl=''
7833         local runlevel_path=$( type -p runlevel )
7834         if [[ -n $runlevel_path ]];then
7835                 runlvl="$( $runlevel_path | gawk '{ print $2 }' )"
7836         fi
7837         echo $runlvl
7838         eval $LOGFE
7839 }
7840
7841 # note: it appears that at least as of 2014-01-13, /etc/inittab is going to be used for
7842 # default runlevel in upstart/sysvinit. systemd default is not always set so check to see 
7843 # if it's linked.
7844 get_runlevel_default()
7845 {
7846         eval $LOGFS
7847         local default_runlvl=''
7848         local inittab='/etc/inittab'
7849         local systemd_default='/etc/systemd/system/default.target'
7850         local upstart_default='/etc/init/rc-sysinit.conf'
7851         
7852         # note: systemd systems do not necessarily have this link created
7853         if [[ -L $systemd_default  ]];then
7854                 default_runlvl=$( readlink $systemd_default )
7855                 if [[ -n $default_runlvl ]];then
7856                         default_runlvl=$( basename $default_runlvl )
7857                 fi
7858         # http://askubuntu.com/questions/86483/how-can-i-see-or-change-default-run-level
7859         # note that technically default can be changed at boot but for inxi purposes that does
7860         # not matter, we just want to know the system default
7861         elif [[ -e $upstart_default ]];then
7862                 # env DEFAULT_RUNLEVEL=2
7863                 default_runlvl=$( gawk -F '=' '/^env[[:space:]]+DEFAULT_RUNLEVEL/ {
7864                 print $2
7865                 }' $upstart_default )
7866         fi
7867         
7868         # handle weird cases where null but inittab exists
7869         if [[ -z $default_runlvl && -f $inittab ]];then
7870                 default_runlvl=$( gawk -F ':' '
7871                 /^id.*initdefault/ {
7872                         print $2
7873                 }' $inittab )
7874         fi
7875         echo $default_runlvl
7876         eval $LOGFE
7877 }
7878
7879 get_sensors_data()
7880 {
7881         eval $LOGFS
7882         
7883         
7884         local temp_array=''
7885                 
7886         IFS=$'\n'
7887         if [[ -n $Sensors_Data ]];then
7888                 # note: non-configured sensors gives error message, which we need to redirect to stdout
7889                 # also, -F ':' no space, since some cases have the data starting right after,like - :1287
7890                 A_SENSORS_DATA=( $( 
7891                 gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" '
7892                 BEGIN {
7893                         IGNORECASE=1
7894                         core0Temp="" # only if all else fails...
7895                         cpuTemp=""
7896                         cpuTempReal=""
7897                         fanWorking=""
7898                         indexCountaFanMain=0
7899                         indexCountaFanDefault=0
7900                         i=""
7901                         j=""
7902                         moboTemp=""
7903                         moboTempReal=""
7904                         psuTemp=""
7905                         separator=""
7906                         sysFanString=""
7907                         temp1=""
7908                         temp2=""
7909                         tempFanType="" # set to 1 or 2
7910                         tempUnit=""
7911                         tempWorking=""
7912                         tempWorkingUnit=""
7913                 }
7914                 # new data arriving: gpu temp in sensors, have to skip that
7915                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
7916                         while ( getline && !/^$/ ) {
7917                                 # do nothing, just skip it
7918                         }
7919                 }
7920                 # dumping the extra + signs after testing for them,  nobody has negative temps.
7921                 # also, note gawk treats Â° as a space, so we have to get the C/F data
7922                 # there are some guesses here, but with more sensors samples it will get closer.
7923                 # note: using arrays starting at 1 for all fan arrays to make it easier overall
7924                 # more validation because gensub if fails to get match returns full string, so
7925                 # we have to be sure we are working with the actual real string before assiging
7926                 # data to real variables and arrays. Extracting C/F degree unit as well to use
7927                 # when constructing temp items for array. 
7928                 # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign 
7929                 # used, but it is required in testing regex to avoid error.
7930                 /^(M\/B|MB|SIO|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7931                         moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 )
7932                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7933                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7934                                 tempUnit=tempWorkingUnit
7935                         }
7936                 }
7937                 /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7938                         cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7939                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7940                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7941                                 tempUnit=tempWorkingUnit
7942                         }
7943                 }
7944                 /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7945                         psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7946                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7947                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7948                                 tempUnit=tempWorkingUnit
7949                         }
7950                 }
7951                 $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7952                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7953                         if ( temp1 == "" || tempWorking > 0 ) {
7954                                 temp1=tempWorking
7955                         }
7956                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7957                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7958                                 tempUnit=tempWorkingUnit
7959                         }
7960                 }
7961                 $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7962                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7963                         if ( temp2 == "" || tempWorking > 0 ) {
7964                                 temp2=tempWorking
7965                         }
7966                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7967                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7968                                 tempUnit=tempWorkingUnit
7969                         }
7970                 }
7971                 
7972                 # final fallback if all else fails, funtoo user showed sensors putting
7973                 # temp on wrapped second line, not handled
7974                 /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
7975                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
7976                         if ( core0Temp == "" || tempWorking > 0 ) {
7977                                 core0Temp=tempWorking
7978                         }
7979                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
7980                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
7981                                 tempUnit=tempWorkingUnit
7982                         }
7983                 }
7984                 
7985                 # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before
7986                 # $2 starts (like so :1234 RPM), so skip that space test in regex
7987                 /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7988                         aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7989                 }
7990                 /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7991                         aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7992                 }
7993                 /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
7994                         aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
7995                 }
7996                 # note that the counters are dynamically set for fan numbers here
7997                 # otherwise you could overwrite eg aux fan2 with case fan2 in theory
7998                 # note: cpu/mobo/ps are 1/2/3
7999                 # NOTE: test: ! i in array does NOT work, this appears to be an awk/gawk bug
8000                 /^(AUX(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8001                         for ( i = 4; i < 7; i++ ){
8002                                 if ( i in aFanMain ){
8003                                         ##
8004                                 }
8005                                 else {
8006                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8007                                         break
8008                                 }
8009                         }
8010                 }
8011                 /^(AUX([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8012                         for ( i = 5; i < 30; i++ ){
8013                                 if ( i in aFanMain ) {
8014                                         ##
8015                                 }
8016                                 else {
8017                                         sysFanNu = i
8018                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8019                                         break
8020                                 }
8021                         }
8022                 }
8023                 # in rare cases syntax is like: fan1: xxx RPM
8024                 /^(FAN(1)?[ \t:])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8025                         aFanDefault[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8026                 }
8027                 /^FAN([2-9]|1[0-9])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
8028                         fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
8029                         sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 )
8030                         if ( sysFanNu ~ /^([0-9]+)$/ ) {
8031                                 # add to array if array index does not exist OR if number is > existing number
8032                                 if ( sysFanNu in aFanDefault ) {
8033                                         if ( fanWorking >= aFanDefault[sysFanNu] ) {
8034                                                 aFanDefault[sysFanNu]=fanWorking
8035                                         }
8036                                 }
8037                                 else {
8038                                         aFanDefault[sysFanNu]=fanWorking
8039                                 }
8040                         }
8041                 }
8042                 
8043                 END {
8044                         # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo:
8045                         # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment
8046                         if ( temp1 != "" && temp2 != "" ){
8047                                 if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) {
8048                                         tempFanType=userCpuNo
8049                                 }
8050                                 else {
8051                                         # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed
8052                                         # but only if other fan speed is 0
8053                                         if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) {
8054                                                 tempFanType=2
8055                                         }
8056                                         else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) {
8057                                                 tempFanType=1
8058                                         }
8059                                         # then handle the standard case if these fringe cases are false
8060                                         else if ( temp1 >= temp2 ) {
8061                                                 tempFanType=1
8062                                         }
8063                                         else {
8064                                                 tempFanType=2
8065                                         }
8066                                 }
8067                         }
8068                         # need a case for no temps at all reported, like with old intels
8069                         else if ( temp2 == "" && cpuTemp == "" ){
8070                                 if ( temp1 == "" && moboTemp == "" ){
8071                                         tempFanType=1
8072                                 }
8073                                 else if ( temp1 != "" && moboTemp == "" ){
8074                                         tempFanType=1
8075                                 }
8076                                 else if ( temp1 != "" && moboTemp != "" ){
8077                                         tempFanType=1
8078                                 }
8079                         }
8080                         
8081                         # then get the real cpu temp, best guess is hottest is real
8082                         if ( cpuTemp != "" ){
8083                                 cpuTempReal=cpuTemp
8084                         }
8085                         else if ( tempFanType != "" ){
8086                                 if ( tempFanType == 1 ){
8087                                         cpuTempReal=temp1
8088                                 }
8089                                 else {
8090                                         cpuTempReal=temp2
8091                                 }
8092                         }
8093                         else {
8094                                 cpuTempReal=temp1
8095                         }
8096                         # if all else fails, use core0 temp if it is present and cpu is null
8097                         if ( cpuTempReal == "" && core0Temp != "" ) {
8098                                 cpuTempReal=core0Temp
8099                         }
8100
8101                         # then the real mobo temp
8102                         if ( moboTemp != "" ){
8103                                 moboTempReal=moboTemp
8104                         }
8105                         else if ( tempFanType != "" ){
8106                                 if ( tempFanType == 1 ) {
8107                                         moboTempReal=temp2
8108                                 }
8109                                 else {
8110                                         moboTempReal=temp1
8111                                 }
8112                         }
8113                         else {
8114                                 moboTempReal=temp2
8115                         }
8116                         # then set the cpu fan speed
8117                         if ( aFanMain[1] == "" ) {
8118                                 # note, you cannot test for aFanDefault[1] or [2] != "" 
8119                                 # because that creates an array item in gawk just by the test itself
8120                                 if ( tempFanType == 1 && 1 in aFanDefault ) {
8121                                         aFanMain[1]=aFanDefault[1]
8122                                         aFanDefault[1]=""
8123                                 }
8124                                 else if ( tempFanType == 2 && 2 in aFanDefault ) {
8125                                         aFanMain[1]=aFanDefault[2]
8126                                         aFanDefault[2]=""
8127                                 }
8128                         }
8129
8130                         # then we need to get the actual numeric max array count for both fan arrays
8131                         for (i = 0; i <= 29; i++) {
8132                                 if ( i in aFanMain && i > indexCountaFanMain ) {
8133                                         indexCountaFanMain=i
8134                                 }
8135                         }
8136                         for (i = 0; i <= 14; i++) {
8137                                 if ( i in aFanDefault && i > indexCountaFanDefault ) {
8138                                         indexCountaFanDefault=i
8139                                 }
8140                         }
8141                         
8142                         # clear out any duplicates. Primary fan real trumps fan working always if same speed
8143                         for (i = 1; i <= indexCountaFanMain; i++) {
8144                                 if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) {
8145                                         for (j = 1; j <= indexCountaFanDefault; j++) {
8146                                                 if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) {
8147                                                         aFanDefault[j] = ""
8148                                                 }
8149                                         }
8150                                 }
8151                         }
8152
8153                         # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo
8154                         # note that gawk is returning true for some test cases when aFanDefault[j] < 5000
8155                         # which has to be a gawk bug, unless there is something really weird with arrays
8156                         # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually 
8157                         # assign that value below, the > 5000 test works again, and a print of the value
8158                         # shows the proper value, so the corruption might be internal in awk. 
8159                         # Note: gensub is the culprit I think, assigning type string for range 501-1000 but 
8160                         # type integer for all others, this triggers true for >
8161                         for (j = 1; j <= indexCountaFanDefault; j++) {
8162                                 if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) {
8163                                         aFanMain[2] = aFanDefault[j]
8164                                         aFanDefault[j] = ""
8165                                         # then add one if required for output
8166                                         if ( indexCountaFanMain < 2 ) {
8167                                                 indexCountaFanMain = 2
8168                                         }
8169                                 }
8170                         }
8171
8172                         # then construct the sys_fan string for echo, note that iteration 1
8173                         # makes: fanDefaultString separator null, ie, no space or ,
8174                         for (j = 1; j <= indexCountaFanDefault; j++) {
8175                                 fanDefaultString = fanDefaultString separator aFanDefault[j]
8176                                 separator=","
8177                         }
8178                         separator="" # reset to null for next loop
8179                         # then construct the sys_fan string for echo
8180                         for (j = 1; j <= indexCountaFanMain; j++) {
8181                                 fanMainString = fanMainString separator aFanMain[j]
8182                                 separator=","
8183                         }
8184                         
8185                         # and then build the temps:
8186                         if ( moboTempReal != "" ) {
8187                                 moboTempReal = moboTempReal tempUnit
8188                         }
8189                         if ( cpuTempReal != "" ) {
8190                                 cpuTempReal = cpuTempReal tempUnit
8191                         }
8192                         
8193                         # if they are ALL null, print error message. psFan is not used in output currently
8194                         if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) {
8195                                 print "No active sensors found. Have you configured your sensors yet?"
8196                         }
8197                         else {
8198                                 # then build array arrays: 
8199                                 print cpuTempReal "," moboTempReal "," psuTemp
8200                                 # this is for output, a null print line does NOT create a new array index in bash
8201                                 if ( fanMainString == "" ) {
8202                                         fanMainString=","
8203                                 }
8204                                 print fanMainString
8205                                 print fanDefaultString
8206                         }
8207                 }' <<< "$Sensors_Data" ) )
8208         fi
8209         
8210         IFS="$ORIGINAL_IFS"
8211         temp_array=${A_SENSORS_DATA[@]}
8212         log_function_data "A_SENSORS_DATA: $temp_array"
8213 #       echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
8214         eval $LOGFE
8215 }
8216
8217 get_sensors_output()
8218 {
8219         local sensors_path=$( type -p sensors ) sensors_data=''
8220         
8221         if [[ -n $sensors_path ]];then
8222                 sensors_data="$( $sensors_path 2>/dev/null )"
8223                 if [[ -n "$sensors_data" ]];then
8224                         # make sure the file ends in newlines then characters, the newlines are lost in the echo unless
8225                         # the data ends in some characters
8226                         sensors_data="$sensors_data\n\n###" 
8227                 fi
8228         fi
8229         echo -e "$sensors_data"
8230 }
8231
8232 get_shell_data()
8233 {
8234         eval $LOGFS
8235
8236         local shell_type="$( ps -p $PPID -o comm= 2>/dev/null )"
8237         local shell_version='' 
8238         
8239         if [[ $B_EXTRA_DATA == 'true' && -n $shell_type ]];then
8240                 case $shell_type in
8241                         bash)
8242                                 shell_version=$( get_de_app_version "$shell_type" "^GNU[[:space:]]bash,[[:space:]]version" "4" | \
8243                                 sed $SED_RX 's/(\(.*|-release|-version)//' )
8244                                 ;;
8245                         # csh/dash use dpkg package version data, debian/buntu only
8246                         csh)
8247                                 shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
8248                                 ;;
8249                         dash)
8250                                 shell_version=$( get_de_app_version "$shell_type" "$shell_type" "3" )
8251                                 ;;
8252                         ksh)
8253                                 shell_version=$( get_de_app_version "$shell_type" "version" "5" )
8254                                 ;;
8255                         tcsh)
8256                                 shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
8257                                 ;;
8258                         zsh)
8259                                 shell_version=$( get_de_app_version "$shell_type" "^zsh" "2" )
8260                                 ;;
8261                 esac
8262         fi
8263         if [[ -n $shell_version ]];then
8264                 shell_type="$shell_type $shell_version"
8265         fi
8266         echo $shell_type
8267         
8268         eval $LOGFS
8269 }
8270
8271 get_shell_parent()
8272 {
8273         eval $LOGFS
8274         local shell_parent='' script_parent='' 
8275         
8276         # removed --no-headers to make bsd safe, adding in -j to make output the same
8277         script_parent=$( ps -j -fp $PPID 2>/dev/null | gawk '/'"$PPID"'/ { print $3 }' )
8278         log_function_data "script parent: $script_parent"
8279         shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
8280         # no idea why have to do script_parent action twice in su case, but you do, oh well.
8281         if [[ $shell_parent == 'su' ]];then
8282                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
8283                 script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
8284                 shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
8285         fi
8286         echo $shell_parent
8287         log_function_data "shell parent final: $shell_parent"
8288         eval $LOGFE
8289 }
8290
8291 # this will be used for some bsd data types
8292 # args: $1 - option type
8293 get_sysctl_data()
8294 {
8295         eval $LOGFS
8296         
8297         local sysctl_data=''
8298         
8299         if [[ $B_SYSCTL ]];then
8300                 sysctl_data="$( sysctl -$1 )"
8301         fi
8302         # log_function_data "sysctl_data: $sysctl_data"
8303         echo "$sysctl_data"
8304         eval $LOGFE
8305 }
8306
8307 get_tty_console_irc()
8308 {
8309         eval $LOGFS
8310         local tty_number=''
8311         if [[ -n ${IRC_CLIENT} ]];then
8312                 tty_number=$( gawk '
8313                         BEGIN {
8314                                 IGNORECASE=1
8315                         }
8316                         # if multiple irc clients open, can give wrong results
8317                         # so make sure to also use the PPID number to get the right tty
8318                         /.*'$PPID'.*'${IRC_CLIENT}'/ {
8319                                 gsub(/[^0-9]/, "", $7)
8320                                 print $7
8321                                 exit
8322                         }' <<< "$Ps_aux_Data" )
8323         fi
8324         log_function_data "tty_number: $tty_number"
8325         echo $tty_number
8326         eval $LOGFE
8327 }
8328
8329 get_tty_number()
8330 {
8331         eval $LOGFS
8332         
8333         local tty_number=$( basename "$( tty 2>/dev/null )" | sed 's/[^0-9]*//g' )
8334         
8335         echo $tty_number
8336         
8337         eval $LOGFE
8338 }
8339
8340 get_unmounted_partition_data()
8341 {
8342         eval $LOGFS
8343         local a_unmounted_working='' mounted_partitions='' separator='|' unmounted_fs=''
8344         local dev_working='' uuid_working='' label_working='' a_raid_working='' raid_partitions=''
8345         
8346         if [[ $B_PARTITIONS_FILE == 'true' ]];then
8347                 # set dev disk label/uuid data globals
8348                 get_partition_dev_data 'label'
8349                 get_partition_dev_data 'uuid'
8350                 # load the raid data array here so we can exclude its partitions
8351                 if [[ $B_RAID_SET != 'true' ]];then
8352                         get_raid_data
8353                 fi
8354                 # sr0 type cd drives are showing up now as unmounted partitions
8355                 mounted_partitions="scd[0-9]+|sr[0-9]+|cdrom[0-9]*|cdrw[0-9]*|dvd[0-9]*|dvdrw[0-9]*"
8356                 # create list for slicing out the mounted partitions
8357                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
8358                 do
8359                         IFS=","
8360                         a_unmounted_working=( ${A_PARTITION_DATA[i]} )
8361                         IFS="$ORIGINAL_IFS"
8362                         if [[ -n ${a_unmounted_working[6]} ]];then
8363                                 mounted_partitions="$mounted_partitions$separator${a_unmounted_working[6]}"
8364                         fi
8365                 done
8366                 # now we need to exclude the mdraid partitions from the unmounted partition output as well
8367                 for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
8368                 do
8369                         IFS=","
8370                         a_raid_working=( ${A_RAID_DATA[i]} )
8371                         IFS="$ORIGINAL_IFS"
8372                         if [[ -n ${a_raid_working[3]} ]];then
8373                                 raid_partitions=$( sed $SED_RX 's/(\([^\)]*\)|\[[^\]]*\])//g' <<< ${a_raid_working[3]}\
8374                                 | sed 's/[[:space:]]\+/|/g' )
8375                                 mounted_partitions="$mounted_partitions$separator$raid_partitions"
8376                         fi
8377                 done
8378         
8379                 A_UNMOUNTED_PARTITION_DATA=( $( grep -Ev '[[:space:]]('$mounted_partitions')$' $FILE_PARTITIONS | gawk '
8380                 BEGIN {
8381                         IGNORECASE=1
8382                 }
8383                 # note that size 1 means it is a logical extended partition container
8384                 # lvm might have dm-1 type syntax
8385                 # need to exclude loop type file systems, squashfs for example
8386                 /[a-z][0-9]+$|dm-[0-9]+$/ && $3 != 1 && $NF !~ /loop/ {
8387                         size = sprintf( "%.2f", $3*1024/1000**3 )
8388                         print $4 "," size "G"
8389                 }' ) )
8390
8391                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
8392                 do
8393                         IFS=","
8394                         a_unmounted_working=( ${A_UNMOUNTED_PARTITION_DATA[i]} )
8395                         IFS="$ORIGINAL_IFS"
8396                         
8397                         label_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_LABEL"  | gawk '{
8398                                 print $(NF - 2)
8399                         }' )
8400                         uuid_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_UUID"  | gawk '{
8401                                 print $(NF - 2)
8402                         }' )
8403                         unmounted_fs=$( get_unmounted_partition_filesystem "/dev/${a_unmounted_working[0]}" )
8404                         
8405                         IFS=","
8406                         A_UNMOUNTED_PARTITION_DATA[i]=${a_unmounted_working[0]}","${a_unmounted_working[1]}","$label_working","$uuid_working","$unmounted_fs
8407                         IFS="$ORIGINAL_IFS"
8408                 done
8409         fi
8410 #       echo "${A_PARTITION_DATA[@]}"
8411 #       echo "${A_UNMOUNTED_PARTITION_DATA[@]}"
8412         eval $LOGFE
8413 }
8414
8415 # a few notes, normally file -s requires root, but you can set user rights in /etc/sudoers.
8416 # list of file systems: http://en.wikipedia.org/wiki/List_of_file_systems
8417 # args: $1 - /dev/<disk><part> to be tested for
8418 get_unmounted_partition_filesystem()
8419 {
8420         eval $LOGFS
8421         local partition_filesystem='' sudo_command=''
8422         
8423         if [[ $B_FILE_TESTED != 'true' ]];then
8424                 B_FILE_TESTED='true'
8425                 FILE_PATH=$( type -p file )
8426         fi
8427         
8428         if [[ $B_SUDO_TESTED != 'true' ]];then
8429                 B_SUDO_TESTED='true'
8430                 SUDO_PATH=$( type -p sudo )
8431         fi
8432         
8433         if [[ -n $FILE_PATH && -n $1 ]];then
8434                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
8435                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
8436                 # important: -n makes it non interactive, no prompt for password
8437                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
8438                         sudo_command='sudo -n '
8439                 fi
8440                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
8441                 # note the hack that simply slices out the first line if > 1 items found in string
8442                 # also, if grub/lilo is on partition boot sector, no file system data is available
8443                 # BSD fix: -Eio -Em 1
8444                 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 '.*' )
8445                 if [[ -n $partition_filesystem ]];then
8446                         echo $partition_filesystem
8447                 fi
8448         fi
8449         eval $LOGFE
8450 }
8451
8452 ## return uptime string
8453 get_uptime()
8454 {
8455         eval $LOGFS
8456         ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
8457         local uptime_value="$( uptime | gawk '{
8458                 a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
8459                 print a
8460         }' )"
8461         echo "$uptime_value"
8462         log_function_data "uptime_value: $uptime_value"
8463         eval $LOGFE
8464 }
8465
8466 get_weather_data()
8467 {
8468         eval $LOGFS
8469         
8470         local location_site='http://geoip.ubuntu.com/lookup'
8471         local weather_feed='http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query='
8472         local weather_spider='http://wunderground.com/'
8473         local data_grab_error='' wget_error=0 
8474         local b_test_loc=false b_test_weather=false b_debug=false
8475         local test_dir="$HOME/bin/scripts/inxi/data/weather/"
8476         local test_location='location2.xml' test_weather='weather-feed.xml'
8477         local location_data='' location='' weather_data='' location_array_value='' a_location=''
8478         local weather_array_value='' site_elevation='' temp_array=''
8479         
8480         # first we get the location data, once that is parsed and handled, we move to getting the 
8481         # actual weather data, assuming no errors
8482         if [[ -n $ALTERNATE_WEATHER_LOCATION ]];then
8483                 # note, this api does not support spaces in names, replace spaces with + sign.
8484                 location=$ALTERNATE_WEATHER_LOCATION
8485                 # echo $ALTERNATE_WEATHER_LOCATION;exit
8486         else
8487                 if [[ $b_test_loc != 'true' ]];then
8488                         location_data=$( wget -q -t 1 -T $WGET_TIMEOUT -O- $location_site || wget_error=$? )
8489                         log_function_data "$location_data"
8490                         if [[ $wget_error -ne 0 ]];then
8491                                 data_grab_error="Error: location server up but download error - wget: $wget_error"
8492                         fi
8493                         wget_error=0
8494                 else
8495                         if [[ -f $test_dir$test_location ]];then
8496                                 location_data="$( cat $test_dir$test_location )"
8497                         else
8498                                 data_grab_error="Error: location xml local file not found."
8499                         fi
8500                 fi
8501                 if [[ -n $data_grab_error ]];then
8502                         :
8503                 elif [[ -z $( grep -i '<Response' <<< $location_data ) ]];then
8504                         data_grab_error="Error: location downloaded but data contains no xml."
8505                 else
8506                         # clean up xml and make easy to process with newlines, note, bsd sed has no support for inserting
8507                         # \n dircctly so we have to use this hack
8508                         # location_data="$( sed $SED_RX 's|><|>\n<|g' <<< $location_data )"
8509                         location_data="$( sed $SED_RX 's|><|>\
8510 <|g' <<< $location_data )"
8511                         # echo -e "ld:\n$location_data"
8512                         location_array_value=$( gawk '
8513                         function clean(data) {
8514                                 returnData=""
8515                                 # some lines might be empty, so ignore those
8516                                 if (data !~ /^<[^>]+>$/ ) {
8517                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8518                                 }
8519                                 return returnData
8520                         }
8521                         BEGIN {
8522                                 IGNORECASE=1
8523                                 locationString=""
8524                                 countryCode=""
8525                                 countryCode3=""
8526                                 countryName=""
8527                                 regionCode=""
8528                                 regionName=""
8529                                 city=""
8530                                 postalCode=""
8531                                 latitude=""
8532                                 longitude=""
8533                                 timeZone=""
8534                                 areaCode=""
8535                         }
8536                         /CountryCode/ {
8537                                 if ( $0 ~ /CountryCode3/ ){
8538                                         countryCode3=clean($0)
8539                                 }
8540                                 else {
8541                                         countryCode=clean($0)
8542                                 }
8543                         }
8544                         /CountryName/ {
8545                                 countryName = clean($0)
8546                         }
8547                         /RegionCode/ {
8548                                 regionCode = clean($0)
8549                         }
8550                         /RegionName/ {
8551                                 regionName = clean($0)
8552                         }
8553                         /City/ {
8554                                 city = clean($0)
8555                         }
8556                         /ZipPostalCode/ {
8557                                 postalCode = clean($0)
8558                         }
8559                         /Latitude/ {
8560                                 latitude = clean($0)
8561                         }
8562                         /Longitude/ {
8563                                 longitude = clean($0)
8564                         }
8565                         /TimeZone/ {
8566                                 timeZone = clean($0)
8567                         }
8568                         END {
8569                                 locationString = city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
8570                                 locationString = locationString  ";" latitude "," longitude ";" postalCode ";" timeZone
8571                                 print locationString
8572                         }' <<< "$location_data" )
8573                 fi
8574                 A_WEATHER_DATA[0]=$location_array_value
8575                 IFS=";"
8576                 a_location=( ${A_WEATHER_DATA[0]} )
8577                 IFS="$ORIGINAL_IFS"
8578                 
8579                 # assign location, cascade from most accurate
8580                 # latitude,longitude first
8581                 if [[ -n ${a_location[6]} ]];then
8582                         location="${a_location[6]}"
8583                 # city,state next
8584                 elif [[ -n ${a_location[0]} && -n ${a_location[1]} ]];then
8585                         location="${a_location[0]},${a_location[1]}"
8586                 # postal code last, that can be a very large region
8587                 elif [[ -n ${a_location[7]} ]];then
8588                         location=${a_location[7]}
8589                 fi
8590         fi
8591         if [[ $b_debug == 'true' ]];then
8592                 echo -e "location array:\n${A_WEATHER_DATA[0]}"
8593                 echo "location: $location"
8594         fi
8595         log_function_data "location: $location"
8596         
8597         if [[ -z $location && -z $data_grab_error ]];then
8598                 data_grab_error="Error: location data downloaded but no location detected."
8599         fi
8600
8601         # now either dump process or go on to get weather data
8602         if [[ -z $data_grab_error ]];then
8603                 if [[ $b_test_weather != 'true' ]];then
8604                         weather_data="$( wget -q -t 1 -T $WGET_TIMEOUT -O- $weather_feed"$location" || wget_error=$? )"
8605                         if [[ $wget_error -ne 0 ]];then
8606                                 data_grab_error="Error: weather server up but download error - wget: $wget_error"
8607                         fi
8608                         log_function_data "$weather_data"
8609                 else
8610                         if [[ -f $test_dir$test_weather ]];then
8611                                 weather_data="$( cat $test_dir$test_weather)"
8612                         else
8613                                 data_grab_error="Error: weather feed xml local file not found."
8614                         fi
8615                 fi
8616                 if [[ -z $data_grab_error && -z $( grep -i '<current_observation' <<< $weather_data ) ]];then
8617                         data_grab_error="Error: weather data downloaded but shows no xml start."
8618                 fi
8619                 if [[ -z $data_grab_error ]];then
8620                         # trim off zeros
8621                         weather_data=$( sed 's/^[[:space:]]*//' <<< "$weather_data" )
8622                         site_elevation=$( grep -im 1 '<elevation>' <<< "$weather_data" | sed $SED_RX -e 's/<[^>]*>//g' \
8623                         -e 's/\.[0-9]*//' )
8624                         # we need to grab the location data from the feed for remote checks 
8625                         if [[ -n $ALTERNATE_WEATHER_LOCATION && -n $weather_data ]];then
8626                                 location_data=$( sed -e '/<current_observation>/,/<display_location>/d' -e '/<\/display_location>/,/<\/current_observation>/d' <<< "$weather_data" )
8627                                 # echo -e "ld1:\n$location_data"
8628                                 A_WEATHER_DATA[0]=$( gawk '
8629                                 function clean(data) {
8630                                         returnData=""
8631                                         # some lines might be empty, so ignore those
8632                                         if (data !~ /^<[^>]+>$/ ) {
8633                                                 returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8634                                                 gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
8635                                         }
8636                                         return returnData
8637                                 }
8638                                 BEGIN {
8639                                         IGNORECASE=1
8640                                         city=""
8641                                         state=""
8642                                         country=""
8643                                 }
8644                                 /<city>/ {
8645                                         city=clean($0)
8646                                 }
8647                                 /<state>/ {
8648                                         state=clean($0)
8649                                 }
8650                                 /<country>/ {
8651                                         country=clean($0)
8652                                 }
8653                                 END {
8654                                         print city ";" state ";;;;" country
8655                                 }' <<< "$location_data" )
8656                                 # echo -e "location:\n${A_WEATHER_DATA[0]}"
8657                         fi
8658                         
8659                         # clean off everything before/after observation_location
8660                         weather_data=$( sed -e '/<current_observation>/,/<observation_location>/d' \
8661                         -e '/<icons>/,/<\/current_observation>/d' <<< "$weather_data" -e 's/^[[:space:]]*$//g' -e '/^$/d' )
8662                         
8663                         # echo "$weather_data";exit 
8664                         weather_array_value=$( gawk -v siteElevation="$site_elevation" '
8665                         function clean(data) {
8666                                 returnData=""
8667                                 # some lines might be empty, so ignore those
8668                                 if (data !~ /^<[^>]+>$/ ) {
8669                                         returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
8670                                         gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
8671                                 }
8672                                 return returnData
8673                         }
8674                         BEGIN {
8675                                 IGNORECASE=1
8676                                 observationTime=""
8677                                 localTime=""
8678                                 weather=""
8679                                 tempString=""
8680                                 humidity=""
8681                                 windString=""
8682                                 pressureString=""
8683                                 dewpointString=""
8684                                 heatIndexString=""
8685                                 windChillString=""
8686                                 weatherString=""
8687                         }
8688                         /observation_time>/ {
8689                                 observationTime=clean($0)
8690                                 sub(/Last Updated on /, "", observationTime )
8691                         }
8692                         /local_time>/ {
8693                                 localTime=clean($0)
8694                         }
8695                         /<weather/ {
8696                                 weather=clean($0)
8697                         }
8698                         /temperature_string/ {
8699                                 tempString=clean($0)
8700                         }
8701                         /relative_humidity/ {
8702                                 humidity=clean($0)
8703                         }
8704                         /wind_string/ {
8705                                 windString=clean($0)
8706                         }
8707                         /pressure_string/ {
8708                                 pressureString=clean($0)
8709                         }
8710                         /heat_index_string/ {
8711                                 heatIndexString=clean($0)
8712                         }
8713                         /windchill_string/ {
8714                                 windChillString=clean($0)
8715                         }
8716                         END {
8717                                 weatherString = observationTime ";" localTime ";" weather ";" tempString ";" humidity 
8718                                 weatherString = weatherString ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
8719                                 weatherString = weatherString ";" windChillString ";" siteElevation
8720                                 print weatherString
8721                         }' <<< "$weather_data" )
8722                 fi
8723                 if [[ -z $weather_array_value ]];then
8724                         data_grab_error="Error: weather info downloaded but no data detected."
8725                 else
8726                         A_WEATHER_DATA[1]=$weather_array_value
8727                 fi
8728         fi
8729         # now either dump process or go on to get weather data
8730         if [[ -n $data_grab_error ]];then
8731                 A_WEATHER_DATA=$data_grab_error
8732                 log_function_data "data grab error: $data_grab_error"
8733         fi
8734         
8735         if [[ $b_debug == 'true' ]];then
8736                 echo "site_elevation: $site_elevation"
8737                 echo "${A_WEATHER_DATA[1]}"
8738         fi
8739         temp_array=${A_WEATHER_DATA[@]}
8740         log_function_data "A_WEATHER_DATA: $temp_array"
8741         
8742         eval $LOGFE
8743 }
8744 # ALTERNATE_WEATHER_LOCATION='portland,or'
8745 # get_weather_data;exit
8746
8747 #### -------------------------------------------------------------------
8748 #### special data handling for specific options and conditions
8749 #### -------------------------------------------------------------------
8750
8751 # args: $1 - string to strip color code characters out of
8752 # returns count of string length minus colors
8753 calculate_line_length()
8754 {
8755         local string="$1"
8756         # ansi: \e[1;34m irc: \x0312
8757         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 )
8758         count=${#string}
8759         echo $count
8760 }
8761
8762 ## multiply the core count by the data to be calculated, bmips, cache
8763 # args: $1 - string to handle; $2 - cpu count
8764 calculate_multicore_data()
8765 {
8766         eval $LOGFS
8767         local string_number=$1 string_data=''
8768
8769         if [[ -n $( grep -Ei '( mb| kb)' <<< $1 ) ]];then
8770                 string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output
8771                 string_number=$( gawk '{print $1}' <<< $1 )
8772         fi
8773         # handle weird error cases where it's not a number
8774         if [[ -n $( grep -E '^[0-9\.,]+$' <<< $string_number ) ]];then
8775                 string_number=$( echo $string_number $2 | gawk '{
8776                         total = $1*$2
8777                         print total
8778                 }' )
8779         elif [[ $string_number == '' ]];then
8780                 string_number='N/A'
8781         else
8782                 # I believe that the above returns 'unknown' by default so no need for extra text
8783                 string_number="$string_number "
8784         fi
8785         echo "$string_number$string_data"
8786         log_function_data "string_numberstring_data: $string_number$string_data"
8787         eval $LOGFE
8788 }
8789
8790 # prints out shortened list of flags, the main ones of interest
8791 # args: $1 - string of cpu flags to process
8792 process_cpu_flags()
8793 {
8794         eval $LOGFS
8795         
8796         local cpu_flags_working=$1
8797         local bits=$( uname -m | grep 64 )
8798         
8799         # no need to show pae for 64 bit cpus, it's pointless
8800         if [[ -n $bits ]];then
8801                 cpu_flags_working=$( sed 's/[[:space:]]*pae//' <<< "$cpu_flags_working" )
8802         fi
8803         # must have a space after last item in list for RS=" "
8804         cpu_flags_working="$cpu_flags_working "
8805         
8806         # nx = AMD stack protection extensions
8807         # lm = Intel 64bit extensions
8808         # sse, sse2, pni = sse1,2,3,4,5 gfx extensions
8809         # svm = AMD pacifica virtualization extensions
8810         # vmx = Intel IVT (vanderpool) virtualization extensions
8811         cpu_flags=$( 
8812         echo "$cpu_flags_working" | gawk '
8813         BEGIN {
8814                 RS=" "
8815                 count = 0
8816                 i = 1 # start at one because of for increment issue
8817                 flag_string = ""
8818         }
8819         
8820         /^(lm|nx|pae|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/ {
8821                 if ( $0 == "pni" ){
8822                         a_flags[i] = "sse3"
8823                 }
8824                 else {
8825                         a_flags[i] = $0
8826                 }
8827                 i++
8828         }
8829         END {
8830                 count = asort( a_flags )
8831                 # note: why does gawk increment before the loop and not after? weird.
8832                 for ( i=0; i <= count; i++ ){
8833                         if ( flag_string == "" ) {
8834                                 flag_string = a_flags[i] 
8835                         }
8836                         else {
8837                                 flag_string = flag_string " " a_flags[i]
8838                         }
8839                 }
8840                 print flag_string
8841         }' )
8842
8843         #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' '))
8844         if [[ -z $cpu_flags ]];then
8845                 cpu_flags="-"
8846         fi
8847         echo "$cpu_flags"
8848         log_function_data "cpu_flags: $cpu_flags"
8849         eval $LOGFE
8850 }
8851
8852 #### -------------------------------------------------------------------
8853 #### print and processing of output data
8854 #### -------------------------------------------------------------------
8855
8856 #### MASTER PRINT FUNCTION - triggers all line item print functions
8857 ## main function to print out, master for all sub print functions.
8858 print_it_out()
8859 {
8860         eval $LOGFS
8861         # note that print_it_out passes local variable values on to its children,
8862         # and in some cases, their children, with Lspci_v_Data
8863         local Lspci_v_Data='' Lspci_n_Data='' # only for verbose
8864         local Sysctl_a_Data='' Dmesg_Boot_Data=''
8865         
8866         if [[ -n $BSD_TYPE ]];then
8867                 Sysctl_a_Data="$( get_sysctl_data 'a' )"
8868                 Dmesg_Boot_Data="$( get_dmesg_boot_data )"
8869         fi
8870
8871         if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then
8872                 print_short_data
8873         else
8874                 Lspci_v_Data="$( get_lspci_data 'v' )"
8875                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
8876                         Lspci_n_Data="$( get_lspci_data 'n' )"
8877                 fi
8878                 if [[ $B_SHOW_SYSTEM == 'true' ]];then
8879                         print_system_data
8880                 fi
8881                 if [[ $B_SHOW_MACHINE == 'true' ]];then
8882                         print_machine_data
8883                 fi
8884                 if [[ $B_SHOW_WEATHER == 'true' ]];then
8885                         print_weather_data
8886                 fi
8887                 if [[ $B_SHOW_BASIC_CPU == 'true' || $B_SHOW_CPU == 'true' ]];then
8888                         print_cpu_data
8889                 fi
8890                 if [[ $B_SHOW_GRAPHICS == 'true' ]];then
8891                         print_graphics_data
8892                 fi
8893                 if [[ $B_SHOW_AUDIO == 'true' ]];then
8894                         print_audio_data
8895                 fi
8896                 if [[ $B_SHOW_NETWORK == 'true' ]];then
8897                         print_networking_data
8898                 fi
8899                 if [[ $B_SHOW_DISK_TOTAL == 'true' || $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
8900                         print_hard_disk_data
8901                 fi
8902                 if [[ $B_SHOW_PARTITIONS == 'true' ]];then
8903                         print_partition_data
8904                 fi
8905                 if [[ $B_SHOW_RAID == 'true' || $B_SHOW_BASIC_RAID == 'true' ]];then
8906                         print_raid_data
8907                 fi
8908                 if [[ $B_SHOW_UNMOUNTED_PARTITIONS == 'true' ]];then
8909                         print_unmounted_partition_data
8910                 fi
8911                 if [[ $B_SHOW_SENSORS == 'true' ]];then
8912                         print_sensors_data
8913                 fi
8914                 if [[ $B_SHOW_REPOS == 'true' ]];then
8915                         print_repo_data
8916                 fi
8917                 if [[ $B_SHOW_PS_CPU_DATA == 'true' || $B_SHOW_PS_MEM_DATA == 'true' ]];then
8918                         print_ps_data
8919                 fi
8920                 if [[ $B_SHOW_INFO == 'true' ]];then
8921                         print_info_data
8922                 fi
8923         fi
8924         eval $LOGFE
8925 }
8926
8927 #### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0
8928 # all the get data stuff is loaded here to keep execution time down for single line print commands
8929 # these will also be loaded in each relevant print function for long output
8930 print_short_data()
8931 {
8932         eval $LOGFS
8933         local current_kernel=$( get_kernel_version ) 
8934         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
8935         local short_data='' i='' b_background_black='false'
8936         local memory=$( get_memory_data )
8937         local up_time="$( get_uptime )"
8938
8939         # set A_CPU_CORE_DATA
8940         get_cpu_core_count
8941         local cpc_plural='' cpu_count_print='' model_plural=''
8942         local cpu_physical_count=${A_CPU_CORE_DATA[0]}
8943         local cpu_core_count=${A_CPU_CORE_DATA[3]}
8944         local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
8945         local cpu_type=${A_CPU_CORE_DATA[2]}
8946
8947         if [[ $cpu_physical_count -gt 1 ]];then
8948                 cpc_plural='(s)'
8949                 model_plural='s'
8950                 cpu_count_print="$cpu_physical_count "
8951         fi
8952
8953         local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
8954 #       local cpu_core_count=${A_CPU_CORE_DATA[0]}
8955
8956         # load A_HDD_DATA
8957         get_hdd_data_basic
8958         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
8959         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
8960         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
8961         IFS=","
8962         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
8963         IFS="$ORIGINAL_IFS"
8964         local hdd_capacity=${a_hdd_basic_working[0]}
8965         local hdd_used=${a_hdd_basic_working[1]}
8966
8967         # load A_CPU_DATA
8968         get_cpu_data
8969
8970         IFS=","
8971         local a_cpu_working=(${A_CPU_DATA[0]})
8972         IFS="$ORIGINAL_IFS"
8973         local cpu_model="${a_cpu_working[0]}"
8974         ## assemble data for output
8975         local cpu_clock="${a_cpu_working[1]}" # old CPU3
8976         # this gets that weird min/max final array item, which almost never contains any data of use
8977         local min_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
8978         local min_max_clock=${A_CPU_DATA[$min_max_clock_nu]}
8979         # this handles the case of for example ARM cpus, which will not have data for
8980         # min/max, since they don't have speed. Since that sets a flag, not found, just
8981         # look for that and use the speed from the first array array, same where we got 
8982         # model from
8983         if [[ "$min_max_clock" == 'N/A' && ${a_cpu_working[1]} != '' ]];then
8984                 min_max_clock="${a_cpu_working[1]} MHz"
8985         fi
8986         local patch_version_number=$( get_patch_version_string )
8987
8988         #set_color_scheme 12
8989         if [[ $B_RUNNING_IN_SHELL == 'false' ]];then
8990                 for i in $C1 $C2 $CN
8991                 do
8992                         case "$i" in
8993                                 "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN")
8994                                         b_background_black='true'
8995                                         ;;
8996                         esac
8997                 done
8998                 if [[ $b_background_black == 'true' ]];then
8999                         for i in C1 C2 CN
9000                         do
9001                                 ## these need to be in quotes, don't know why
9002                                 if [[ ${!i} == $NORMAL ]];then
9003                                         declare $i="${!i}15,1"
9004                                 else
9005                                         declare $i="${!i},1"
9006                                 fi
9007                         done
9008                         #C1="${C1},1"; C2="${C2},1"; CN="${CN},1"
9009                 fi
9010         fi
9011         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}"
9012
9013         if [[ $SHOW_IRC -gt 0 ]];then
9014                 short_data="${short_data}${C1}Client${C2}${SEP1}${IRC_CLIENT}${IRC_CLIENT_VERSION}${SEP2}"
9015         fi
9016         short_data="${short_data}${C1}$SCRIPT_NAME${C2}${SEP1}$SCRIPT_VERSION_NUMBER$patch_version_number${SEP2}${CN}"
9017         if [[ $SCHEME -gt 0 ]];then
9018                 short_data="${short_data} $NORMAL"
9019         fi
9020         print_screen_output "$short_data"
9021         eval $LOGFE
9022 }
9023
9024 #### LINE ITEM PRINT FUNCTIONS
9025
9026 # print sound card data
9027 print_audio_data()
9028 {
9029         eval $LOGFS
9030         local i='' card_id='' audio_data='' a_audio_data='' port_data='' pci_bus_id='' card_string=''
9031         local a_audio_working='' audio_driver='' alsa_data='' port_plural='' module_version='' chip_id=''
9032         local bus_usb_text='' bus_usb_id='' line_starter='Audio:' alsa='' alsa_version='' print_data=''
9033         local driver=''
9034         # set A_AUDIO_DATA and get alsa data
9035         if [[ $BSD_TYPE == 'bsd' ]];then
9036                 if [[ $B_PCICONF_SET == 'false' ]];then
9037                         get_pciconf_data
9038                 fi
9039                 get_pciconf_card_data 'audio'
9040         else
9041                 get_audio_data
9042         fi
9043         
9044         get_audio_alsa_data
9045         # alsa driver data now prints out no matter what
9046         if [[ -n $A_ALSA_DATA ]];then
9047                 IFS=","
9048                 if [[ -n ${A_ALSA_DATA[0]} ]];then
9049                         alsa=${A_ALSA_DATA[0]}
9050                 else
9051                         alsa='N/A'
9052                 fi
9053                 if [[ -n ${A_ALSA_DATA[1]} ]];then
9054                         alsa_version=${A_ALSA_DATA[1]}
9055                 else
9056                         alsa_version='N/A'
9057                 fi
9058                 alsa_data="${C1}Sound:${C2} $alsa ${C1}ver$SEP3${C2} $alsa_version"
9059                 IFS="$ORIGINAL_IFS"
9060         fi
9061         # note, error handling is done in the get function, so this will never be null, but
9062         # leaving the test just in case it's changed.
9063         if [[ -n ${A_AUDIO_DATA[@]} ]];then
9064                 for (( i=0; i< ${#A_AUDIO_DATA[@]}; i++ ))
9065                 do
9066                         IFS=","
9067                         a_audio_working=( ${A_AUDIO_DATA[i]} )
9068                         IFS="$ORIGINAL_IFS"
9069                         port_data=''
9070                         audio_driver=''
9071                         audio_data=''
9072                         card_string=''
9073                         port_plural=''
9074                         module_version=''
9075                         pci_bus_id=''
9076                         bus_usb_text=''
9077                         bus_usb_id=''
9078                         print_data=''
9079                         card_id=''
9080                         chip_id=''
9081                         
9082                         if [[ ${#A_AUDIO_DATA[@]} -gt 1 ]];then
9083                                 card_id="-$(( $i + 1 ))"
9084                         fi
9085                         if [[ $BSD_TYPE != 'bsd' ]];then
9086                                 if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then
9087                                         module_version=$( print_module_version "${a_audio_working[3]}" 'audio' )
9088                                 elif [[ -n ${a_audio_working[1]} && $B_EXTRA_DATA == 'true' ]];then
9089                                         module_version=$( print_module_version "${a_audio_working[1]}" 'audio' )
9090                                 fi
9091                         fi
9092                         # we're testing for the presence of the 2nd array item here, which is the driver name
9093                         if [[ -n ${a_audio_working[1]} ]];then
9094                                 # note: linux drivers can have numbers, like tg3
9095                                 if [[ $BSD_TYPE == 'bsd' ]];then
9096                                         driver=$( sed 's/[0-9]$//' <<< ${a_audio_working[1]} )
9097                                 else
9098                                         driver=${a_audio_working[1]}
9099                                 fi
9100                                 audio_driver="${C1}driver$SEP3${C2} ${driver} "
9101                         fi
9102                         if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then
9103                                 if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then
9104                                         port_plural='s'
9105                                 fi
9106                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_audio_working[2]} "
9107                         fi
9108                         if [[ -n ${a_audio_working[4]} && $B_EXTRA_DATA == 'true' ]];then
9109                                 if [[ ${a_audio_working[1]} != 'USB Audio' ]];then
9110                                         bus_usb_text='bus-ID'
9111                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9112                                                 if [[ $BSD_TYPE != 'bsd' ]];then
9113                                                         chip_id=$( get_lspci_chip_id "${a_audio_working[4]}" )
9114                                                 else
9115                                                         chip_id=${a_audio_working[6]}
9116                                                 fi
9117                                         fi
9118                                 else
9119                                         bus_usb_text='usb-ID'
9120                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9121                                                 chip_id=${a_audio_working[5]}
9122                                         fi
9123                                 fi
9124                                 bus_usb_id=${a_audio_working[4]}
9125                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id "
9126                                 if [[ -n $chip_id ]];then
9127                                         chip_id="${C1}chip-ID$SEP3${C2} $chip_id "
9128                                 fi
9129                         fi
9130                         if [[ -n ${a_audio_working[0]} ]];then
9131                                 card_string="${C1}Card$card_id:${C2} ${a_audio_working[0]} "
9132                                 audio_data="$audio_driver$port_data$pci_bus_id$chip_id"
9133                         fi
9134                         # only print alsa on last line if short enough, otherwise print on its own line
9135                         if [[ $i -eq 0 ]];then
9136                                 if [[ -n $alsa_data && $( calculate_line_length "$card_string${audio_data}$alsa_data" ) -lt $COLS_INNER ]];then
9137                                         audio_data="$audio_data$alsa_data"
9138                                         alsa_data=''
9139                                 fi
9140                         fi
9141                         if [[ -n $audio_data ]];then
9142                                 if [[ $( calculate_line_length "$card_string$audio_data" ) -lt $COLS_INNER ]];then
9143                                         print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
9144                                         print_screen_output "$print_data"
9145                                 # print the line
9146                                 else
9147                                         # keep the driver on the same line no matter what, looks weird alone on its own line
9148                                         if [[ $B_EXTRA_DATA != 'true' ]];then
9149                                                 print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
9150                                                 print_screen_output "$print_data"
9151                                         else
9152                                                 print_data=$( create_print_line "$line_starter" "$card_string" )
9153                                                 print_screen_output "$print_data"
9154                                                 line_starter=' '
9155                                                 print_data=$( create_print_line "$line_starter" "$audio_data" )
9156                                                 print_screen_output "$print_data"
9157                                         fi
9158                                 fi
9159                                 line_starter=' '
9160                         fi
9161                 done
9162         fi
9163         if [[ -n $alsa_data ]];then
9164                 alsa_data=$( sed 's/ALSA/Advanced Linux Sound Architecture/' <<< $alsa_data )
9165                 alsa_data=$( create_print_line "$line_starter" "$alsa_data" )
9166                 print_screen_output "$alsa_data"
9167         fi
9168         eval $LOGFE
9169 }
9170
9171 print_cpu_data()
9172 {
9173         eval $LOGFS
9174         local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data=''
9175         local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' flag_feature='flags'
9176         local a_cpu_working='' cpu_model='' cpu_clock='' cpu_null_error=''
9177         local cpc_plural='' cpu_count_print='' model_plural='' cpu_data_string=''
9178         local cpu_physical_count='' cpu_core_count='' cpu_core_alpha='' cpu_type=''
9179         local cpu_2_data=''
9180
9181         ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\""
9182         # Array A_CPU_DATA always has one extra element: max clockfreq found.
9183         # that's why its count is one more than you'd think from cores/cpus alone
9184         # load A_CPU_DATA
9185         get_cpu_data
9186
9187         IFS=","
9188         a_cpu_working=(${A_CPU_DATA[0]})
9189         IFS="$ORIGINAL_IFS"
9190
9191         # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1
9192         # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>"
9193         # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_,
9194         # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note.
9195         # This has been confirmed by #bash on freenode.
9196         # The above mentioned only emerges when using the debugging markers below
9197         ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------"
9198         # unless all these are null, process whatever you have
9199         if [[ -n ${a_cpu_working[0]} || -n ${a_cpu_working[1]} || -n ${a_cpu_working[2]} || -n ${a_cpu_working[3]} ]];then
9200                 cpu_model="${a_cpu_working[0]}"
9201                 ## assemble data for output
9202                 cpu_clock="${a_cpu_working[1]}"
9203
9204                 cpu_vendor=${a_cpu_working[5]}
9205
9206                 # set A_CPU_CORE_DATA
9207                 get_cpu_core_count
9208                 cpu_physical_count=${A_CPU_CORE_DATA[0]}
9209                 cpu_core_count=${A_CPU_CORE_DATA[3]}
9210                 cpu_core_alpha=${A_CPU_CORE_DATA[1]}
9211                 cpu_type=${A_CPU_CORE_DATA[2]}
9212                 
9213                 if [[ $cpu_physical_count -gt 1 ]];then
9214                         cpc_plural='(s)'
9215                         cpu_count_print="$cpu_physical_count "
9216                         model_plural='s'
9217                 fi
9218
9219                 cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
9220                 cpu_data=$( create_print_line "CPU$cpc_plural:" "${C1}${cpu_data_string}${C2} ${a_cpu_working[0]}$model_plural (${cpu_type})" )
9221                 if [[ $B_SHOW_CPU == 'true' ]];then
9222                         # update for multicore, bogomips x core count.
9223                         if [[ $B_EXTRA_DATA == 'true' ]];then
9224         #                       if [[ $cpu_vendor != 'intel' ]];then
9225                                 # ARM may use the faked 1 cpucorecount to make this work
9226                                 # echo $cpu_core_count $cpu_physical_count
9227                                 if [[ -n ${a_cpu_working[4]} ]];then
9228                                         bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
9229                                 fi
9230         #                       else
9231         #                               bmip_data="${a_cpu_working[4]}"
9232         #                       fi
9233                                 # bogomips are a linux thing, but my guess is over time bsds will use them somewhere anyway
9234                                 if [[ $BSD_TYPE == 'bsd' && -z $bmip_data ]];then
9235                                         bmip_data=''
9236                                 else
9237                                         bmip_data="${C1}bmips$SEP3${C2} $bmip_data "
9238                                 fi
9239                         fi
9240                         ## note: this handles how intel reports L2, total instead of per core like AMD does
9241                         # note that we need to multiply by number of actual cpus here to get true cache size
9242                         if [[ -n ${a_cpu_working[2]} ]];then
9243                                 if [[ $cpu_vendor != 'intel' ]];then
9244                                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))"  )
9245                                 else
9246                                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count"  )
9247                                 fi
9248                         else
9249                                 cpu_cache='N/A'
9250                         fi
9251                         # only print shortened list
9252                         if [[ $B_CPU_FLAGS_FULL != 'true' ]];then
9253                                 # gawk has already sorted this output, no flags returns -
9254                                 if [[ $B_EXTRA_DATA == 'true' ]];then
9255                                         cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" "${a_cpu_working[6]}" )
9256                                         cpu_flags="($cpu_flags)"
9257                                         if [[ ${a_cpu_working[6]} == 'true' ]];then
9258                                                 flag_feature='features'
9259                                         fi
9260                                         cpu_flags="${C1}$flag_feature$SEP3${C2} $cpu_flags "
9261                                 fi
9262                         fi
9263                         # arm cpus do not have flags or cache
9264                         if [[ ${a_cpu_working[6]} != 'true' ]];then
9265                                 cpu_data="$cpu_data${C2} ${C1}cache$SEP3${C2} $cpu_cache${CN}"
9266                                 cpu_2_data="$cpu_flags$bmip_data${CN}"
9267                         else
9268                                 cpu_data="$cpu_data${C2} (ARM)$bmip_data${CN}"
9269                         fi
9270                 fi
9271                 # we don't this printing out extra line unless > 1 cpu core
9272                 if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
9273                         cpu_clock_speed='' # null < verbosity level 5
9274                 else
9275                         cpu_data="$cpu_data ${C1}clocked at${C2} ${a_cpu_working[1]} MHz${CN}"
9276                 fi
9277                 cpu_2_data="$cpu_2_data$cpu_clock_speed"
9278         else
9279                 if [[ $BSD_TYPE == 'bsd' && $B_ROOT != 'true' ]];then
9280                         cpu_null_error=' No permissions for sysctl use?'
9281                 fi
9282                 cpu_data=$( create_print_line "CPU:" "${C2}No CPU data available.$cpu_null_error" )
9283         fi
9284         # echo ln: $( calculate_line_length "$cpu_data $cpu_2_data" )
9285         # echo icols: $COLS_INNER
9286         # echo tc: $TERM_COLUMNS
9287         # echo :$cpu_2_data:
9288         if [[ -n $cpu_2_data && $( calculate_line_length "$cpu_data $cpu_2_data" ) -gt $COLS_INNER ]];then
9289                 print_screen_output "$cpu_data"
9290                 cpu_data=$( create_print_line " " "$cpu_2_data" )
9291                 print_screen_output "$cpu_data"
9292         else
9293                 print_screen_output "$cpu_data $cpu_2_data"
9294         fi
9295         # we don't this printing out extra line unless > 1 cpu core
9296         # note the numbering, the last array item is the min/max/not found for cpu speeds
9297         if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
9298                 for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ ))
9299                 do
9300                         IFS=","
9301                         a_cpu_working=(${A_CPU_DATA[i]})
9302                         IFS="$ORIGINAL_IFS"
9303                         # note: the first iteration will create a first space, for color code separation below
9304                         cpu_multi_clock_data="$cpu_multi_clock_data ${C1}$(( i + 1 )):${C2} ${a_cpu_working[1]} MHz${CN}"
9305                         # someone actually appeared with a 16 core system, so going to stop the cpu core throttle
9306                         # if this had some other purpose which we can't remember we'll add it back in
9307                         #if [[ $i -gt 10 ]];then
9308                         #       break
9309                         #fi
9310                 done
9311                 if [[ -n $cpu_multi_clock_data ]];then
9312                         cpu_multi_clock_data=$( create_print_line " " "${C1}Clock Speeds:${C2}$cpu_multi_clock_data" )
9313                         print_screen_output "$cpu_multi_clock_data"
9314                 fi
9315         fi
9316         if [[ $B_CPU_FLAGS_FULL == 'true' ]];then
9317                 print_cpu_flags_full "${a_cpu_working[3]}" "${a_cpu_working[6]}"
9318         fi
9319         eval $LOGFE
9320 }
9321
9322 # takes list of all flags, split them and prints x per line
9323 # args: $1 - cpu flag string; $2 - arm true/false
9324 print_cpu_flags_full()
9325 {
9326         eval $LOGFS
9327         # note: sort only sorts lines, not words in a string, so convert to lines
9328         local cpu_flags_full="$( echo $1 | tr " " "\n" | sort )" 
9329         local a_cpu_flags='' line_starter='' temp_string=''
9330         local i=0 counter=0 starter_length=15 flag='' flag_data=''
9331         local line_length='' flag_feature='Flags' spacer='' flag_string=''
9332         
9333         if [[ $2 == 'true' ]];then
9334                 flag_feature='Features'
9335         fi
9336         # build the flag line array
9337         for flag in $cpu_flags_full
9338         do
9339                 temp_string="$flag_string$spacer$flag"
9340                 spacer=' '
9341                 # handle inner line starter
9342                 if [[ $counter -eq 0 ]];then
9343                         line_length=$(( $COLS_INNER - $starter_length ))
9344                 else
9345                         line_length=$COLS_INNER
9346                 fi
9347                 if [[ ${#temp_string} -gt $line_length ]];then
9348                         a_cpu_flags[$counter]=$temp_string
9349                         flag_string=''
9350                         spacer=''
9351                         (( counter++ ))
9352                 else
9353                         flag_string=$temp_string
9354                 fi
9355                 temp_string=''
9356         done
9357         if [[ -n $flag_string ]];then
9358                 a_cpu_flags[$counter]=$flag_string
9359         fi
9360         # then print it out
9361         for (( i=0; i < ${#a_cpu_flags[@]};i++ ))
9362         do
9363                 if [[ $i -eq 0 ]];then
9364                         line_starter="${C1}CPU $flag_feature$SEP3${C2} "
9365                 else
9366                         line_starter=''
9367                 fi
9368                 flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" )
9369                 print_screen_output "$flag_data"
9370         done
9371         eval $LOGFE
9372 }
9373
9374 print_graphics_data()
9375 {
9376         eval $LOGFS
9377         local graphics_data='' card_id='' i='' root_alert='' root_x_string='' a_graphics_working=''
9378         local b_is_mesa='false' display_full_string='' card_bus_id='' card_data=''
9379         local res_tty='Resolution' xorg_data='' display_vendor_string='' chip_id=''
9380         local spacer='' driver='' driver_string='' driver_plural='' direct_render_string=''
9381         local separator_loaded='' separator_unloaded='' separator_failed='' 
9382         local loaded='' unloaded='' failed='' display_server_string=''
9383         local line_starter='Graphics:'
9384         local screen_resolution="$( get_graphics_res_data )"
9385         
9386         # set A_DISPLAY_SERVER_DATA
9387         get_graphics_display_server_data
9388         local display_vendor=${A_DISPLAY_SERVER_DATA[0]}
9389         local display_version=${A_DISPLAY_SERVER_DATA[1]}
9390         # set A_GLX_DATA
9391         get_graphics_glx_data
9392         local glx_renderer="${A_GLX_DATA[0]}"
9393         local glx_version="${A_GLX_DATA[1]}"
9394         # this can contain a long No case debugging message, so it's being sliced off
9395         # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why
9396         local glx_direct_render=$( gawk '{print $1}' <<< "${A_GLX_DATA[2]}" )
9397
9398         # set A_GRAPHICS_CARD_DATA
9399         if [[ $BSD_TYPE == 'bsd' ]];then
9400                 if [[ $B_PCICONF_SET == 'false' ]];then
9401                         get_pciconf_data
9402                 fi
9403                 get_pciconf_card_data 'display'
9404         else
9405                 get_graphics_card_data
9406         fi
9407         # set A_GRAPHIC_DRIVERS
9408         get_graphics_driver
9409         
9410         if [[ ${#A_GRAPHIC_DRIVERS[@]} -eq 0 ]];then
9411                 driver=' N/A'
9412         else
9413                 for (( i=0; i < ${#A_GRAPHIC_DRIVERS[@]}; i++ ))
9414                 do
9415                         IFS=","
9416                         a_graphics_working=( ${A_GRAPHIC_DRIVERS[i]} )
9417                         IFS="$ORIGINAL_IFS"
9418                         case ${a_graphics_working[1]} in
9419                                 loaded)
9420                                         loaded="$loaded$separator_loaded${a_graphics_working[0]}"
9421                                         separator_loaded=','
9422                                         ;;
9423                                 unloaded)
9424                                         unloaded="$unloaded$separator_unloaded${a_graphics_working[0]}"
9425                                         separator_unloaded=','
9426                                         ;;
9427                                 failed)
9428                                         failed="$failed$separator_failed${a_graphics_working[0]}"
9429                                         separator_failed=','
9430                                         ;;              
9431                         esac
9432                 done
9433         fi
9434         if [[ -n $loaded ]];then
9435                 driver="${driver} $loaded"
9436         fi
9437         if [[ -n $unloaded ]];then
9438                 driver="${driver} (unloaded: $unloaded)"
9439         fi
9440         if [[ -n $failed ]];then
9441                 driver="${driver} ${RED}FAILED:${C2} $failed"
9442         fi
9443         # sometimes for some reason there is no driver found but the array is started
9444         if [[ -z $driver ]];then
9445                 driver=' N/A'
9446         fi
9447
9448         if [[ ${#A_GRAPHIC_DRIVERS[@]} -gt 1 ]];then
9449                 driver_plural='s'
9450         fi
9451         driver_string="${C1}driver$driver_plural$SEP3${C2}$driver "
9452         
9453         # some basic error handling:
9454         if [[ -z $screen_resolution ]];then
9455                 screen_resolution='N/A'
9456         fi
9457         if [[ -z $display_vendor || -z $display_version ]];then
9458                 display_vendor_string="N/A"
9459         else
9460                 display_vendor_string="$display_vendor $display_version"
9461         fi
9462         display_server_string="${C1}Display Server${SEP3}${C2} $display_vendor_string "
9463
9464         if [[ $B_ROOT == 'true' ]];then
9465                 root_x_string='for root '
9466                 if [[ $B_RUNNING_IN_SHELL == 'true' || $B_CONSOLE_IRC == 'true' ]];then
9467                         res_tty='tty size'
9468                 fi
9469         fi
9470         if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
9471                 root_x_string="${root_x_string}out of X"
9472                 res_tty='tty size'
9473         fi
9474         
9475         if [[ -n $root_x_string ]];then
9476                 root_x_string="${C1}Advanced Data:${C2} N/A $root_x_string"
9477         fi
9478
9479         display_full_string="$display_server_string$driver_string${C1}${res_tty}$SEP3${C2} ${screen_resolution} $root_x_string"
9480
9481         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 0 ]];then
9482                 for (( i=0; i < ${#A_GRAPHICS_CARD_DATA[@]}; i++ ))
9483                 do
9484                         IFS=","
9485                         a_graphics_working=( ${A_GRAPHICS_CARD_DATA[i]} )
9486                         IFS="$ORIGINAL_IFS"
9487                         card_bus_id=''
9488                         card_data=${a_graphics_working[0]}
9489                         if [[ $B_EXTRA_DATA == 'true' ]];then
9490                                 if [[ -n ${a_graphics_working[1]} ]];then
9491                                         card_bus_id=" ${C1}bus-ID$SEP3${C2} ${a_graphics_working[1]}"
9492                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9493                                                 if [[ $BSD_TYPE != 'bsd' ]];then
9494                                                         chip_id=$( get_lspci_chip_id "${a_graphics_working[1]}" )
9495                                                 else
9496                                                         chip_id=${a_graphics_working[2]}
9497                                                 fi
9498                                         fi
9499                                 else
9500                                         card_bus_id=" ${C1}bus-ID$SEP3${C2} N/A"
9501                                 fi
9502                         fi
9503                         if [[ -n $chip_id ]];then
9504                                 chip_id=" ${C1}chip-ID$SEP3${C2} $chip_id"
9505                         fi
9506                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
9507                                 card_id="Card-$(($i+1)):"
9508                         else
9509                                 card_id='Card:'
9510                         fi
9511                         graphics_data="${C1}$card_id${C2} $card_data$card_bus_id$chip_id "
9512                         if [[ ${#A_GRAPHICS_CARD_DATA[@]} -gt 1 ]];then
9513                                 graphics_data=$( create_print_line "$line_starter" "${graphics_data}" )
9514                                 print_screen_output "$graphics_data"
9515                                 line_starter=' '
9516                                 graphics_data=''
9517                         fi
9518                 done
9519         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
9520         else
9521                 graphics_data="${C1}Card:${C2} Failed to Detect Video Card! "
9522         fi
9523         if [[ -n $graphics_data && $( calculate_line_length "${graphics_data}$display_full_string" ) -lt $COLS_INNER ]];then
9524                 graphics_data=$( create_print_line "$line_starter" "${graphics_data}$display_full_string" )
9525         else
9526                 if [[ -n $graphics_data ]];then
9527                         graphics_data=$( create_print_line "$line_starter" "$graphics_data" )
9528                         print_screen_output "$graphics_data"
9529                         line_starter=' '
9530                 fi
9531                 graphics_data=$( create_print_line "$line_starter" "$display_full_string" )
9532         fi
9533         print_screen_output "$graphics_data"
9534         # if [[ -z $glx_renderer || -z $glx_version ]];then
9535         #       b_is_mesa='true'
9536         # fi
9537
9538         ## note: if glx render or display_version have no content, then mesa is true
9539         # if [[ $B_SHOW_DISPLAY_DATA == 'true' ]] && [[ $b_is_mesa != 'true' ]];then
9540         if [[ $B_SHOW_DISPLAY_DATA == 'true' && $B_ROOT != 'true' ]];then
9541                 if [[ -z $glx_renderer ]];then
9542                         glx_renderer='N/A'
9543                 fi
9544                 if [[ -z $glx_version ]];then
9545                         glx_version='N/A'
9546                 fi
9547                 if [[ -z $glx_direct_render ]];then
9548                         glx_direct_render='N/A'
9549                 fi
9550                 if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then
9551                         direct_render_string=" ${C1}Direct Rendering$SEP3${C2} ${glx_direct_render}${CN}"
9552                 fi
9553                 graphics_data="${C1}GLX Renderer$SEP3${C2} ${glx_renderer} ${C1}GLX Version$SEP3${C2} ${glx_version}${CN}$direct_render_string"
9554                 graphics_data=$( create_print_line " " "$graphics_data" )
9555                 
9556                 print_screen_output "$graphics_data"
9557         fi
9558         eval $LOGFE
9559 }
9560
9561 print_hard_disk_data()
9562 {
9563         eval $LOGFS
9564         local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string=''
9565         local hdd_serial=''
9566         local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name='' divisor=5
9567         local Line_Starter='Drives:' # inherited by print_optical_drives
9568
9569         # load A_HDD_DATA
9570         get_hdd_data_basic
9571         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
9572         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
9573         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
9574         IFS=","
9575         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
9576         IFS="$ORIGINAL_IFS"
9577         local hdd_capacity="${a_hdd_basic_working[0]}"
9578         local hdd_used=${a_hdd_basic_working[1]}
9579         local bsd_unsupported='Hard drive data not yet supported for BSD systems.'
9580         local hdd_name_temp=''
9581
9582         if [[ $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
9583         ## note: the output part of this should be in the print hdd data function, not here
9584                 get_hard_drive_data_advanced
9585                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
9586                 do
9587                         # this adds the (x) numbering in front of each disk found, and creates the full disk string
9588                         IFS=","
9589                         a_hdd_working=( ${A_HDD_DATA[i]} )
9590                         IFS="$ORIGINAL_IFS"
9591                         if [[ $B_SHOW_DISK == 'true' ]];then
9592                                 if [[ -n ${a_hdd_working[3]} ]];then
9593                                         usb_data="${a_hdd_working[3]} "
9594                                 else
9595                                         usb_data=''
9596                                 fi
9597                                 dev_data="/dev/${a_hdd_working[0]} "
9598                                 size_data=" ${C1}size$SEP3${C2} ${a_hdd_working[1]}"
9599                                 if [[ $B_EXTRA_DATA == 'true' && -n $dev_data ]];then
9600                                         hdd_temp_data=$( get_hdd_temp_data "$dev_data" )
9601                                         # error handling is done in get data function
9602                                         if [[ -n $hdd_temp_data ]];then
9603                                                 hdd_temp_data=" ${C1}temp$SEP3${C2} ${hdd_temp_data}C"
9604                                         else
9605                                                 hdd_temp_data=''
9606                                         fi
9607                                 fi
9608                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9609                                         hdd_serial=$( get_hdd_serial_number "${a_hdd_working[0]}" )
9610                                         if [[ -z $hdd_serial ]];then
9611                                                 hdd_serial='N/A'
9612                                         fi
9613                                         hdd_serial=" ${C1}serial$SEP3${C2} $hdd_serial"
9614                                         divisor=1 # print every line
9615                                 else
9616                                         divisor=2 # for modulus line print out, either 2 items for full, or default for short
9617                                 fi
9618                                 dev_data="${C1}id$SEP3${C2} /dev/${a_hdd_working[0]} "
9619                         fi
9620                         if [[ -n ${a_hdd_working[2]} ]];then
9621                                 hdd_name_temp=${a_hdd_working[2]}
9622                         else
9623                                 hdd_name_temp='N/A'
9624                         fi
9625                         hdd_name="${C1}model$SEP3${C2} $hdd_name_temp"
9626                         hdd_string="$usb_data$dev_data$hdd_name$size_data$hdd_serial$hdd_temp_data"
9627                         hdd_model="${hdd_model}${C1}$(($i+1)):${C2} $hdd_string "
9628                         # printing line one, then new lines according to $divisor setting, and after, if leftovers, print that line.
9629                         case $i in 
9630                                 0)
9631                                         if [[ $divisor -eq 1 ]];then
9632                                                 hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})" )
9633                                                 print_screen_output "$hdd_data"
9634                                                 Line_Starter=' '
9635                                                 hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}" )
9636                                                 print_screen_output "$hdd_data"
9637                                                 hdd_model=''
9638                                         else
9639                                                 hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used}) ${hdd_model}" )
9640                                                 print_screen_output "$hdd_data"
9641                                                 hdd_model=''
9642                                                 Line_Starter=' '
9643                                         fi
9644                                         ;;
9645                                 *)
9646                                         # using modulus here, if divisible by $divisor, print line, otherwise skip
9647                                         if [[ $(( $i % $divisor )) -eq 0 ]];then
9648                                                 hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
9649                                                 print_screen_output "$hdd_data"
9650                                                 hdd_model=''
9651                                                 Line_Starter=' '
9652                                         fi
9653                                         ;;
9654                         esac
9655                 done
9656                 # then print any leftover items
9657                 if [[ -n $hdd_model ]];then
9658                         hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
9659                         print_screen_output "$hdd_data"
9660                 fi
9661                 # temporary message to indicate not yet supported
9662                 if [[ $BSD_TYPE == 'bsd' ]];then
9663                         hdd_data=$bsd_unsupported
9664                         hdd_data=$( create_print_line "$Line_Starter" "$hdd_data${CN}" )
9665                         print_screen_output "$hdd_data"
9666                         Line_Starter=' '
9667                 fi
9668         else
9669                 # temporary message to indicate not yet supported
9670                 hdd_data="${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})"
9671                 if [[ $BSD_TYPE == 'bsd' ]];then
9672                         hdd_data=$bsd_unsupported
9673                 fi
9674                 hdd_data=$( create_print_line "$Line_Starter" "$hdd_data${CN}" )
9675                 print_screen_output "$hdd_data"
9676                 Line_Starter=' '
9677         fi
9678         if [[ $B_SHOW_FULL_OPTICAL == 'true' || $B_SHOW_BASIC_OPTICAL == 'true' ]];then
9679                 print_optical_drive_data
9680         fi
9681
9682         eval $LOGFE
9683 }
9684
9685 print_info_data()
9686 {
9687         eval $LOGFS
9688
9689         local info_data='' line_starter='Info:' runlvl_default='' runlvl='' runlvl_title='runlevel' 
9690         local init_data='' init_type='' init_version='' rc_type='' rc_version=''
9691         local client_data='' shell_data='' shell_parent='' tty_session=''
9692         local memory="$( get_memory_data )"
9693         local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
9694         local up_time="$( get_uptime )"
9695         local patch_version_number=$( get_patch_version_string )
9696         local gcc_string='' gcc_installed='' gcc_others='' closing_data='' 
9697         
9698         if [[ -z $memory ]];then
9699                 memory='N/A'
9700         fi
9701         
9702         if [[ $B_EXTRA_DATA == 'true' ]];then
9703                 get_gcc_system_version
9704                 if [[ ${#A_GCC_VERSIONS[@]} -gt 0 ]];then
9705                         if [[ -n ${A_GCC_VERSIONS[0]} ]];then
9706                                 gcc_installed=${A_GCC_VERSIONS[0]}
9707                         else
9708                                 gcc_installed='N/A'
9709                         fi
9710                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_GCC_VERSIONS[1]} ]];then
9711                                 gcc_others=" ${C1}alt$SEP3${C2} $( tr ',' '/' <<< ${A_GCC_VERSIONS[1]} )"
9712                         fi
9713                         gcc_installed="${C1}Gcc sys$SEP3${C2} $gcc_installed$gcc_others "
9714                 fi
9715         fi
9716         if [[  $B_RUNNING_IN_SHELL == 'true' ]];then
9717                 shell_data=$( get_shell_data )
9718                 if [[ -n $shell_data ]];then
9719                         # note, if you start this in tty, it will give 'login' as the parent, which we don't want.
9720                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9721                                 if [[ $B_RUNNING_IN_DISPLAY != 'true' ]];then
9722                                         shell_parent=$( get_tty_number )
9723                                         shell_parent="tty $shell_parent"
9724                                 else
9725                                         shell_parent=$( get_shell_parent )
9726                                 fi
9727                                 if [[ $shell_parent == 'login' ]];then
9728                                         shell_parent=''
9729                                 elif [[ -n $shell_parent ]];then
9730                                         shell_parent=" running in $shell_parent"
9731                                 fi
9732                         fi
9733                         IRC_CLIENT="$IRC_CLIENT ($shell_data$shell_parent)"
9734                 fi
9735         fi
9736
9737         # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch!
9738         # long_last=$( echo -ne "${C1}Processes$SEP3${C2} ${processes}${CN} | ${C1}Uptime$SEP3${C2} ${up_time}${CN} | ${C1}Memory$SEP3${C2} ${MEM}${CN}" )
9739         info_data="${C1}Processes$SEP3${C2} ${processes} ${C1}Uptime$SEP3${C2} ${up_time} ${C1}Memory$SEP3${C2} ${memory}${CN} "
9740
9741         # this only triggers if no X data is present or if extra data switch is on
9742         if [[ $B_SHOW_DISPLAY_DATA != 'true' || $B_EXTRA_DATA == 'true' ]];then
9743                 get_init_data
9744                 if [[ ${A_INIT_DATA[0]} == 'systemd' && -z $( grep -E '^[0-9]$' <<< ${A_INIT_DATA[4]} ) ]];then
9745                         runlvl_title='target'
9746                 fi
9747                 init_type=${A_INIT_DATA[0]}
9748                 if [[ -z $init_type ]];then
9749                         init_type='N/A'
9750                 fi
9751                 
9752                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
9753                         init_version=${A_INIT_DATA[1]}
9754                         if [[ -z $init_version ]];then
9755                                 init_version='N/A'
9756                         fi
9757                         init_version=" ${C1}v$SEP3${C2} $init_version"
9758                         rc_version=${A_INIT_DATA[3]}
9759                         if [[ -n $rc_version ]];then
9760                                 rc_version=" ${C1}v$SEP3${C2} $rc_version"
9761                         fi
9762                         
9763                         runlvl_default=${A_INIT_DATA[5]}
9764                 fi
9765                 # currently only using openrc here, otherwise show nothing
9766                 rc_type=${A_INIT_DATA[2]}
9767                 if [[ -n $rc_type ]];then
9768                         rc_type=" ${C1}rc$SEP3${C2} $rc_type$rc_version"
9769                 fi
9770                 init_type="${C1}Init$SEP3${C2} $init_type$init_version "
9771                 
9772                 runlvl=${A_INIT_DATA[4]}
9773                 if [[ -n $runlvl ]];then
9774                         runlvl="${C1}$runlvl_title$SEP3${C2} $runlvl "
9775                 fi
9776                 if [[ -n $runlvl_default ]];then
9777                         runlvl_default="${C1}default$SEP3${C2} $runlvl_default "
9778                 fi
9779                 init_data="$init_type$rc_type$runlvl$runlvl_default"
9780         fi
9781         if [[ $SHOW_IRC -gt 0 ]];then
9782                 client_data="${C1}Client$SEP3${C2} ${IRC_CLIENT}${IRC_CLIENT_VERSION} "
9783         fi
9784         info_data="${info_data}"
9785         closing_data="$client_data${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number${CN}"
9786         
9787         # sometimes gcc is very long, and default runlevel can be long with systemd, so create a gcc-less line first
9788         if [[ $( calculate_line_length "${info_data}${init_data}${gcc_installed}${closing_data}" ) -gt $COLS_INNER ]];then
9789                 info_data=${info_data}${init_data}
9790                 info_data=$( create_print_line "$line_starter" "$info_data" )
9791                 print_screen_output "$info_data"
9792                 init_data=''
9793                 info_data=''
9794                 # closing_data=''
9795                 line_starter=' '
9796                 #echo 1
9797         fi
9798         if [[ $( calculate_line_length "${info_data}${init_data}${gcc_installed}${closing_data}" ) -gt $COLS_INNER ]];then
9799                 info_data=${info_data}${init_data}${gcc_installed}
9800                 info_data=$( create_print_line "$line_starter" "$info_data" )
9801                 print_screen_output "$info_data"
9802                 info_data=''
9803                 gcc_installed=''
9804                 init_data=''
9805                 line_starter=' '
9806                 #echo 2
9807         fi
9808         info_data="${info_data}${init_data}${gcc_installed}${closing_data}"
9809         
9810         info_data=$( create_print_line "$line_starter" "$info_data" )
9811         if [[ $SCHEME -gt 0 ]];then
9812                 info_data="${info_data} ${NORMAL}"
9813         fi
9814         print_screen_output "$info_data"
9815         
9816         eval $LOGFE
9817 }
9818
9819 print_machine_data()
9820 {
9821         eval $LOGFS
9822         
9823         local system_line='' mobo_line='' bios_line='' chassis_line=''
9824         local mobo_vendor='' mobo_model='' mobo_version='' mobo_serial=''
9825         local bios_vendor='' bios_version='' bios_date='' bios_rom=''
9826         local system_vendor='' product_name='' product_version='' product_serial='' product_uuid=''
9827         local chassis_vendor='' chassis_type='' chassis_version='' chassis_serial='' 
9828         local b_skip_system='false' b_skip_chassis='false'
9829         local sysDmiError='No /sys/class/dmi, using '
9830         local sysDmiNull='No /sys/class/dmi machine data: try newer kernel, or install dmidecode'
9831         # set A_MACHINE_DATA
9832         get_machine_data
9833         
9834         if [[ -n $BSD_TYPE ]];then
9835                 sysDmiError=''
9836                 sysDmiNull='No machine data available. Is dmidecode installed?'
9837         fi
9838
9839         IFS=','
9840         ## keys for machine data are:
9841         # 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid 
9842         # 5-board_vendor 6-board_name 7-board_version 8-board_serial 
9843         # 9-bios_vendor 10-bios_version 11-bios_date 
9844         ## with extra data: 
9845         # 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial
9846         
9847         if [[ ${#A_MACHINE_DATA[@]} -gt 0 ]];then
9848                 # note: in some case a mobo/version will match a product name/version, do not print those
9849                 # but for laptops, or even falsely id'ed desktops with batteries, let's print it all if it matches
9850                 # there can be false id laptops if battery appears so need to make sure system is filled
9851                 if [[ -z ${A_MACHINE_DATA[0]} ]];then
9852                         b_skip_system='true'
9853                 else
9854                         if [[ $B_PORTABLE != 'true'  ]];then
9855                                 # ibm / ibm can be true; dell / quantum is false, so in other words, only do this
9856                                 # in case where the vendor is the same and the version is the same and not null, 
9857                                 # otherwise the version information is going to be different in all cases I think
9858                                 if [[ -n ${A_MACHINE_DATA[0]} && ${A_MACHINE_DATA[0]} == ${A_MACHINE_DATA[5]} ]];then
9859                                         if [[ -n ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[2]} == ${A_MACHINE_DATA[7]} ]] || \
9860                                         [[ -z ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[1]} == ${A_MACHINE_DATA[6]} ]];then
9861                                                 b_skip_system='true'
9862                                         fi
9863                                 fi
9864                         fi
9865                 fi
9866                 # no point in showing chassis if system isn't there, it's very unlikely that would be correct
9867                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && $b_skip_system != 'true' ]];then
9868                         if [[ -n ${A_MACHINE_DATA[7]} && ${A_MACHINE_DATA[14]} == ${A_MACHINE_DATA[7]} ]];then
9869                                 b_skip_chassis='true'
9870                         fi
9871                         if [[ -n ${A_MACHINE_DATA[12]} && $b_skip_chassis != 'true' ]];then
9872                                 # no need to print the vendor string again if it's the same
9873                                 if [[ ${A_MACHINE_DATA[12]} != ${A_MACHINE_DATA[0]} ]];then
9874                                         chassis_vendor=" ${A_MACHINE_DATA[12]}"
9875                                 fi
9876                                 if [[ -n ${A_MACHINE_DATA[13]} ]];then
9877                                         chassis_type=" ${C1}type$SEP3${C2} ${A_MACHINE_DATA[13]}"
9878                                 fi
9879                                 if [[ -n ${A_MACHINE_DATA[14]} ]];then
9880                                         chassis_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[14]}"
9881                                 fi
9882                                 if [[ -n ${A_MACHINE_DATA[15]} && $B_OUTPUT_FILTER != 'true' ]];then
9883                                         chassis_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[15]}"
9884                                 fi
9885                                 if [[ -n "$chassis_vendor$chassis_type$chassis_version$chassis_serial" ]];then
9886                                         chassis_line="${C1}Chassis$SEP3${C2}$chassis_vendor$chassis_type$chassis_version$chassis_serial"
9887                                 fi
9888                         fi
9889                 fi
9890                 if [[ -n ${A_MACHINE_DATA[5]} ]];then
9891                         mobo_vendor=${A_MACHINE_DATA[5]}
9892                 else
9893                         mobo_vendor='N/A'
9894                 fi
9895                 if [[ -n ${A_MACHINE_DATA[6]} ]];then
9896                         mobo_model=${A_MACHINE_DATA[6]}
9897                 else
9898                         mobo_model='N/A'
9899                 fi
9900                 if [[ -n ${A_MACHINE_DATA[7]} ]];then
9901                         mobo_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[7]}"
9902                 fi
9903                 if [[ -n ${A_MACHINE_DATA[8]} && $B_OUTPUT_FILTER != 'true' ]];then
9904                         mobo_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[8]}"
9905                 fi
9906                 if [[ -n ${A_MACHINE_DATA[9]} ]];then
9907                         bios_vendor=${A_MACHINE_DATA[9]}
9908                 else
9909                         bios_vendor='N/A'
9910                 fi
9911                 if [[ -n ${A_MACHINE_DATA[10]} ]];then
9912                         bios_version=${A_MACHINE_DATA[10]}
9913                         if [[ -n ${A_MACHINE_DATA[16]} ]];then
9914                                 bios_version="$bios_version rv ${A_MACHINE_DATA[16]}"
9915                         fi
9916                 else
9917                         bios_version='N/A'
9918                 fi
9919                 if [[ -n ${A_MACHINE_DATA[11]} ]];then
9920                         bios_date=${A_MACHINE_DATA[11]}
9921                 else
9922                         bios_date='N/A'
9923                 fi
9924                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_MACHINE_DATA[17]} ]];then
9925                         bios_rom=" ${C1}rom size$SEP3${C2} ${A_MACHINE_DATA[17]}"
9926                 fi
9927                 mobo_line="${C1}Mobo$SEP3${C2} $mobo_vendor ${C1}model$SEP3${C2} $mobo_model$mobo_version$mobo_serial"
9928                 bios_line="${C1}Bios$SEP3${C2} $bios_vendor ${C1}version$SEP3${C2} $bios_version ${C1}date$SEP3${C2} $bios_date$bios_rom"
9929                 if [[ $( calculate_line_length "$mobo_line$bios_line" ) -lt $COLS_INNER ]];then
9930                         mobo_line="$mobo_line $bios_line"
9931                         bios_line=''
9932                 fi
9933                 if [[ $b_skip_system == 'true' ]];then
9934                         system_line=$mobo_line
9935                         mobo_line=''
9936                 else
9937                         # this has already been tested for above so we know it's not null
9938                         system_vendor=${A_MACHINE_DATA[0]}
9939                         if [[ $B_PORTABLE == 'true' ]];then
9940                                 system_vendor="$system_vendor (portable)"
9941                         fi
9942                         if [[ -n ${A_MACHINE_DATA[1]} ]];then
9943                                 product_name=${A_MACHINE_DATA[1]}
9944                         else
9945                                 product_name='N/A'
9946                         fi
9947                         if [[ -n ${A_MACHINE_DATA[2]} ]];then
9948                                 product_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[2]}"
9949                         fi
9950                         if [[ -n ${A_MACHINE_DATA[3]} && $B_OUTPUT_FILTER != 'true' ]];then
9951                                 product_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[3]} "
9952                         fi
9953                         system_line="${C1}System$SEP3${C2} $system_vendor ${C1}product$SEP3${C2} $product_name$product_version$product_serial"
9954                         if [[ -n $chassis_line && $( calculate_line_length "$system_line$chassis_line" ) -lt $COLS_INNER ]];then
9955                                 system_line="$system_line $chassis_line"
9956                                 chassis_line=''
9957                         fi
9958                 fi
9959                 IFS="$ORIGINAL_IFS"
9960         else
9961                 system_line="${C2}$sysDmiNull${CN}"
9962         fi
9963         # patch to dump all of above if dmidecode was data source and non root user
9964         if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' || ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
9965                 if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' ]];then
9966                         system_line="${C2}${sysDmiError}dmidecode: you must be root to run dmidecode${CN}"
9967                 elif [[ ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
9968                         system_line="${C2}${sysDmiError}dmidecode: no machine data available${CN}"
9969                 fi
9970                 mobo_line=''
9971                 bios_line=''
9972                 chassis_line=''
9973         fi
9974         system_line=$( create_print_line "Machine:" "$system_line" )
9975         print_screen_output "$system_line"
9976         if [[ -n $mobo_line ]];then
9977                 mobo_line=$( create_print_line " " "$mobo_line" )
9978                 print_screen_output "$mobo_line"
9979         fi
9980         if [[ -n $bios_line ]];then
9981                 bios_line=$( create_print_line " " "$bios_line" )
9982                 print_screen_output "$bios_line"
9983         fi
9984         if [[ -n $chassis_line ]];then
9985                 chassis_line=$( create_print_line " " "$chassis_line" )
9986                 print_screen_output "$chassis_line"
9987         fi
9988         
9989         eval $LOGFE
9990 }
9991
9992 # args: $1 - module name (could be > 1, so loop it ); $2 - audio (optional)
9993 print_module_version()
9994 {
9995         eval $LOGFS
9996         local module_versions='' module='' version='' prefix='' modules=$1
9997         
9998         # note that sound driver data tends to have upper case, but modules are lower
9999         if [[ $2 == 'audio' ]];then
10000                 if [[ -z $( grep -E '^snd' <<< $modules ) ]];then
10001                         prefix='snd_' # sound modules start with snd_
10002                 fi
10003                 modules=$( tr '[A-Z]' '[a-z]' <<< $modules )
10004                 modules=$( tr '-' '_' <<< $modules )
10005                 # special intel processing, generally no version info though
10006                 if [[ $modules == 'hda intel' ]];then
10007                         modules='hda_intel'
10008                 elif [[ $modules == 'intel ich' ]];then
10009                         modules='intel8x0'
10010                 fi
10011         fi
10012
10013         for module in $modules
10014         do
10015                 version=$( get_module_version_number "$prefix$module" )
10016                 if [[ -n $version ]];then
10017                         module_versions="$module_versions $version"
10018                 fi
10019         done
10020
10021         if [[ -n $module_versions ]];then
10022                 echo " ${C1}ver$SEP3${C2}$module_versions"
10023         fi
10024         eval $LOGFE
10025 }
10026
10027 print_networking_data()
10028 {
10029         eval $LOGFS
10030         local i='' card_id='' network_data='' a_network_working='' port_data='' driver_data=''
10031         local card_string='' port_plural='' module_version='' pci_bus_id='' bus_usb_text=''
10032         local bus_usb_id='' line_starter='Network:' card_string='' card_data='' chip_id=''
10033         local driver=''
10034         # set A_NETWORK_DATA
10035         if [[ $BSD_TYPE == 'bsd' ]];then
10036                 if [[ $B_PCICONF_SET == 'false' ]];then
10037                         get_pciconf_data
10038                 fi
10039                 get_pciconf_card_data 'network'
10040         else
10041                 get_networking_data
10042         fi
10043
10044         # will never be null because null is handled in get_network_data, but in case we change
10045         # that leaving this test in place.
10046         if [[ -n ${A_NETWORK_DATA[@]} ]];then
10047                 for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
10048                 do
10049                         IFS=","
10050                         a_network_working=( ${A_NETWORK_DATA[i]} )
10051                         IFS="$ORIGINAL_IFS"
10052                         bus_usb_id=''
10053                         bus_usb_text=''
10054                         card_data=''
10055                         card_string=''
10056                         driver_data=''
10057                         module_version=''
10058                         network_data=''
10059                         pci_bus_id=''
10060                         port_data=''
10061                         port_plural=''
10062                         card_id=''
10063                         chip_id=''
10064
10065                         if [[ ${#A_NETWORK_DATA[@]} -gt 1 ]];then
10066                                 chip_id="-$(( $i + 1 ))"
10067                         fi
10068                         if [[ -n ${a_network_working[1]} && $B_EXTRA_DATA == 'true' && $BSD_TYPE != 'bsd' ]];then
10069                                 module_version=$( print_module_version "${a_network_working[1]}" )
10070                         fi
10071                         if [[ -n ${a_network_working[1]} ]];then
10072                                 # note: linux drivers can have numbers, like tg3
10073                                 if [[ $BSD_TYPE == 'bsd' ]];then
10074                                         driver=$( sed 's/[0-9]*$//' <<< ${a_network_working[1]} )
10075                                 else
10076                                         driver=${a_network_working[1]}
10077                                 fi
10078                                 driver_data="${C1}driver$SEP3${C2} ${driver}$module_version "
10079                         fi
10080                         if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then
10081                                 if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then
10082                                         port_plural='s'
10083                                 fi
10084                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_network_working[2]} "
10085                         fi
10086                         if [[ -n ${a_network_working[4]} && $B_EXTRA_DATA == 'true' ]];then
10087                                 if [[ -z $( grep '^usb-' <<< ${a_network_working[4]} ) ]];then
10088                                         bus_usb_text='bus-ID'
10089                                         bus_usb_id=${a_network_working[4]}
10090                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10091                                                 if [[ $BSD_TYPE != 'bsd' ]];then
10092                                                         chip_id=$( get_lspci_chip_id "${a_network_working[4]}" )
10093                                                 else
10094                                                         chip_id=${a_network_working[10]}
10095                                                 fi
10096                                         fi
10097                                 else
10098                                         bus_usb_text='usb-ID'
10099                                         bus_usb_id=$( cut -d '-' -f '2-4' <<< ${a_network_working[4]} )
10100                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10101                                                 chip_id=${a_network_working[10]}
10102                                         fi
10103                                 fi
10104                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id"
10105                                 if [[ -n $chip_id ]];then
10106                                         chip_id=" ${C1}chip-ID$SEP3${C2} $chip_id"
10107                                 fi
10108                         fi
10109                         card_string="${C1}Card$card_id:${C2} ${a_network_working[0]} "
10110                         card_data="$driver_data$port_data$pci_bus_id$chip_id"
10111                         if [[ $( calculate_line_length "$card_string$card_data" ) -gt $COLS_INNER ]];then
10112                                 network_data=$( create_print_line "$line_starter" "$card_string" )
10113                                 line_starter=' '
10114                                 card_string=''
10115                                 print_screen_output "$network_data"
10116                         fi
10117                         network_data=$( create_print_line "$line_starter" "$card_string$card_data" )
10118                         line_starter=' '
10119                         print_screen_output "$network_data"
10120                         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' ]];then
10121                                 print_network_advanced_data
10122                         fi
10123                 done
10124         else
10125                 network_data="${C1}Card:${C2} Failed to Detect Network Card! "
10126                 network_data=$( create_print_line "$line_starter" "$network_data" )
10127                 print_screen_output "$network_data"
10128         fi
10129         if [[ $B_SHOW_IP == 'true' ]];then
10130                 print_networking_ip_data
10131         fi
10132         eval $LOGFE
10133 }
10134
10135 print_network_advanced_data()
10136 {
10137         eval $LOGFS
10138         local network_data='' if_id='N/A' duplex='N/A' mac_id='N/A' speed='N/A' oper_state='N/A'
10139         local b_is_wifi='false' speed_string='' duplex_string=''
10140         
10141                 # first check if it's a known wifi id'ed card, if so, no print of duplex/speed
10142         if [[ -n $( grep -Esi '(wireless|wifi|wi-fi|wlan|802\.11|centrino)' <<< ${a_network_working[0]} ) ]];then
10143                 b_is_wifi='true'
10144         fi
10145         if [[ -n ${a_network_working[5]} ]];then
10146                 if_id=${a_network_working[5]}
10147         fi
10148         if [[ -n ${a_network_working[6]} ]];then
10149                 oper_state=${a_network_working[6]}
10150         fi
10151         # no print out for wifi since it doesn't have duplex/speed data availabe
10152         # note that some cards show 'unknown' for state, so only testing explicitly
10153         # for 'down' string in that to skip showing speed/duplex
10154         if [[ $b_is_wifi != 'true' && $oper_state != 'down' ]];then
10155                 if [[ -n ${a_network_working[7]} ]];then
10156                         # make sure the value is strictly numeric before appending Mbps
10157                         if [[ -n $( grep -E '^[0-9\.,]+$' <<< "${a_network_working[7]}" ) ]];then
10158                                 speed="${a_network_working[7]} Mbps"
10159                         else
10160                                 speed=${a_network_working[7]}
10161                         fi
10162                 fi
10163                 speed_string="${C1}speed$SEP3${C2} $speed "
10164                 if [[ -n ${a_network_working[8]} ]];then
10165                         duplex=${a_network_working[8]}
10166                 fi
10167                 duplex_string="${C1}duplex$SEP3${C2} $duplex "
10168         fi
10169         if [[ -n ${a_network_working[9]} ]];then
10170                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10171                         mac_id=$FILTER_STRING
10172                 else
10173                         mac_id=${a_network_working[9]}
10174                 fi
10175         fi
10176         network_data="${C1}IF:${C2} $if_id ${C1}state$SEP3${C2} $oper_state $speed_string$duplex_string${C1}mac$SEP3${C2} $mac_id"
10177         network_data=$( create_print_line " " "$network_data" )
10178         print_screen_output "$network_data"
10179         
10180         eval $LOGFE
10181 }
10182
10183 print_networking_ip_data()
10184 {
10185         eval $LOGFS
10186         local ip=$( get_networking_wan_ip_data )
10187         local wan_ip_data='' a_interfaces_working='' interfaces='' i=''
10188         local if_id='' if_ip='' if_ipv6='' if_ipv6_string='' full_string='' if_string=''
10189         local if_id_string='' if_ip_string=''
10190         local line_max=$(( $COLS_INNER - 40 ))
10191
10192         # set A_INTERFACES_DATA
10193         get_networking_local_ip_data
10194         # first print output for wan ip line. Null is handled in the get function
10195         if [[ -z $ip ]];then
10196                 ip='N/A'
10197         else
10198                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10199                         ip=$FILTER_STRING
10200                 fi
10201         fi
10202         wan_ip_data="${C1}WAN IP:${C2} $ip "
10203         # then create the list of local interface/ip
10204         i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1
10205         while [[ -n ${A_INTERFACES_DATA[i]} ]]
10206         do
10207                 IFS=","
10208                 a_interfaces_working=(${A_INTERFACES_DATA[i]})
10209                 IFS="$ORIGINAL_IFS"
10210                 if_id='N/A'
10211                 if_ip='N/A'
10212                 if_ipv6='N/A'
10213                 if_ipv6_string=''
10214                 if [[ -z $( grep '^Interface' <<< ${a_interfaces_working[0]} ) ]];then
10215                         if [[ -n ${a_interfaces_working[1]} ]];then
10216                                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
10217                                         if_ip=$FILTER_STRING
10218                                 else
10219                                         if_ip=${a_interfaces_working[1]}
10220                                 fi
10221                         fi
10222                         if_ip_string=" ${C1}ip$SEP3${C2} $if_ip"
10223                         if [[ $B_EXTRA_DATA == 'true' ]];then
10224                                 if [[ -n ${a_interfaces_working[3]} ]];then
10225                                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
10226                                                 if_ipv6=$FILTER_STRING
10227                                         else
10228                                                 if_ipv6=${a_interfaces_working[3]}
10229                                         fi
10230                                 fi
10231                                 if_ipv6_string=" ${C1}ip-v6$SEP3${C2} $if_ipv6"
10232                         fi
10233                 fi
10234                 if [[ -n ${a_interfaces_working[0]} ]];then
10235                         if_id=${a_interfaces_working[0]}
10236                 fi
10237                 if_string="$wan_ip_data$if_string${C1}IF:${C2} $if_id$if_ip_string$if_ipv6_string "
10238                 wan_ip_data=''
10239                 if [[ $( calculate_line_length "$if_string" ) -gt $line_max ]];then
10240                         full_string=$( create_print_line " " "$if_string" )
10241                         print_screen_output "$full_string"
10242                         if_string=''
10243                 fi
10244                 ((i++))
10245         done
10246         
10247         # then print out anything not printed already
10248         if [[ -n $if_string ]];then
10249                 full_string=$( create_print_line " " "$if_string" )
10250                 print_screen_output "$full_string"
10251         fi
10252         eval $LOGFE
10253 }
10254
10255 print_optical_drive_data()
10256 {
10257         eval $LOGFS
10258         local a_drives='' drive_data='' counter='' 
10259         local drive_id='' drive_links='' vendor='' speed='' multisession='' mcn='' audio=''
10260         local dvd='' state='' rw_support='' rev='' separator='' drive_string=''
10261         get_optical_drive_data
10262         # 0 - true dev path, ie, sr0, hdc
10263         # 1 - dev links to true path
10264         # 2 - device vendor - for hdx drives, vendor model are one string from proc
10265         # 3 - device model
10266         # 4 - device rev version
10267         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 0 ]];then
10268                 for (( i=0; i < ${#A_OPTICAL_DRIVE_DATA[@]}; i++ ))
10269                 do
10270                         IFS=","
10271                         a_drives=(${A_OPTICAL_DRIVE_DATA[i]})
10272                         IFS="$ORIGINAL_IFS"
10273                         audio=''
10274                         drive_data=''
10275                         drive_id=''
10276                         drive_links=''
10277                         dvd='' 
10278                         mcn='' 
10279                         multisession='' 
10280                         rev='' 
10281                         rw_support='' 
10282                         separator=''
10283                         speed='' 
10284                         state='' 
10285                         vendor=''
10286                         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -eq 1 && -z ${a_drives[0]} && -z ${a_drives[1]} ]];then
10287                                 drive_string="No optical drives detected."
10288                                 B_SHOW_FULL_OPTICAL='false'
10289                         else
10290                                 if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 1 ]];then
10291                                         counter="-$(( i + 1 ))"
10292                                 fi
10293                                 if [[ -z ${a_drives[0]} ]];then
10294                                         drive_id='N/A'
10295                                 else
10296                                         drive_id="/dev/${a_drives[0]}"
10297                                 fi
10298                                 drive_links=$( sed 's/~/,/g' <<< ${a_drives[1]} )
10299                                 if [[ -z $drive_links ]];then
10300                                         drive_links='N/A'
10301                                 fi
10302                                 if [[ -n ${a_drives[2]} ]];then
10303                                         vendor=${a_drives[2]}
10304                                         if [[ -n ${a_drives[3]} ]];then
10305                                                 vendor="$vendor ${a_drives[3]}"
10306                                         fi
10307                                 fi
10308                                 if [[ -z $vendor ]];then
10309                                         if [[ -n ${a_drives[3]} ]];then
10310                                                 vendor=${a_drives[3]}
10311                                         else
10312                                                 vendor='N/A'
10313                                         fi
10314                                 fi
10315                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10316                                         if [[ -n ${a_drives[4]} ]];then
10317                                                 rev=${a_drives[4]}
10318                                         else
10319                                                 rev='N/A'
10320                                         fi
10321                                         rev=" ${C1}rev$SEP3${C2} $rev"
10322                                 fi
10323                                 drive_string="$drive_id ${C1}model$SEP3${C2} $vendor$rev ${C1}dev-links$SEP3${C2} $drive_links"
10324                         fi
10325                         drive_data="${C1}Optical${counter}:${C2} $drive_string"
10326                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
10327                         print_screen_output "$drive_data"
10328                         Line_Starter=' '
10329                         # 5 - speed
10330                         # 6 - multisession support
10331                         # 7 - MCN support
10332                         # 8 - audio read
10333                         # 9 - cdr
10334                         # 10 - cdrw
10335                         # 11 - dvd read
10336                         # 12 - dvdr
10337                         # 13 - dvdram
10338                         # 14 - state
10339                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
10340                                 if [[ -z ${a_drives[5]} ]];then
10341                                         speed='N/A'
10342                                 else
10343                                         speed="${a_drives[5]}x"
10344                                 fi
10345                                 if [[ -z ${a_drives[8]} ]];then
10346                                         audio='N/A'
10347                                 elif [[ ${a_drives[8]} == 1 ]];then
10348                                         audio='yes'
10349                                 else
10350                                         audio='no'
10351                                 fi
10352                                 audio=" ${C1}audio$SEP3${C2} $audio"
10353                                 if [[ -z ${a_drives[6]} ]];then
10354                                         multisession='N/A'
10355                                 elif [[ ${a_drives[6]} == 1 ]];then
10356                                         multisession='yes'
10357                                 else
10358                                         multisession='no'
10359                                 fi
10360                                 multisession=" ${C1}multisession$SEP3${C2} $multisession"
10361                                 if [[ -z ${a_drives[11]} ]];then
10362                                         dvd='N/A'
10363                                 elif [[ ${a_drives[11]} == 1 ]];then
10364                                         dvd='yes'
10365                                 else
10366                                         dvd='no'
10367                                 fi
10368                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10369                                         if [[ -z ${a_drives[14]} ]];then
10370                                                 state='N/A'
10371                                         else
10372                                                 state="${a_drives[14]}"
10373                                         fi
10374                                         state=" ${C1}state$SEP3${C2} $state"
10375                                 fi
10376                                 if [[ -n ${a_drives[9]} && ${a_drives[9]} == 1 ]];then
10377                                         rw_support='cd-r'
10378                                         separator=','
10379                                 fi
10380                                 if [[ -n ${a_drives[10]} && ${a_drives[10]} == 1 ]];then
10381                                         rw_support="${rw_support}${separator}cd-rw"
10382                                         separator=','
10383                                 fi
10384                                 if [[ -n ${a_drives[12]} && ${a_drives[12]} == 1 ]];then
10385                                         rw_support="${rw_support}${separator}dvd-r"
10386                                         separator=','
10387                                 fi
10388                                 if [[ -n ${a_drives[13]} && ${a_drives[13]} == 1 ]];then
10389                                         rw_support="${rw_support}${separator}dvd-ram"
10390                                         separator=','
10391                                 fi
10392                                 if [[ -z $rw_support ]];then
10393                                         rw_support='none'
10394                                 fi
10395                                 
10396                                 drive_data="${C1}Features: speed$SEP3${C2} $speed$multisession$audio ${C1}dvd$SEP3${C2} $dvd ${C1}rw$SEP3${C2} $rw_support$state"
10397                                 drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
10398                                 print_screen_output "$drive_data"
10399                         fi
10400                 done
10401         else
10402                 :
10403         fi
10404         eval $LOGFE
10405 }
10406
10407 print_partition_data()
10408 {
10409         eval $LOGFS
10410         local a_partition_working='' partition_used='' partition_data=''
10411         local counter=0 i=0 a_partition_data='' line_starter='' line_max=$(( $COLS_INNER - 25 ))
10412         local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label=''
10413         local part_uuid='' full_uuid='' dev_remote='' full_fs='' line_max_label_uuid=$COLS_INNER
10414         local b_non_dev='false' holder=''
10415
10416         # set A_PARTITION_DATA
10417         get_partition_data
10418
10419         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
10420         do
10421                 IFS=","
10422                 a_partition_working=(${A_PARTITION_DATA[i]})
10423                 IFS="$ORIGINAL_IFS"
10424                 full_label=''
10425                 full_uuid=''
10426
10427                 if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then
10428                         if [[ -n ${a_partition_working[2]} ]];then
10429                                 partition_used="${C1}used$SEP3${C2} ${a_partition_working[2]} (${a_partition_working[3]}) "
10430                         else
10431                                 partition_used='' # reset partition used to null
10432                         fi
10433                         if [[ -n ${a_partition_working[5]} ]];then
10434                                 full_fs="${a_partition_working[5]}"
10435                         else
10436                                 full_fs='N/A' # reset partition fs type
10437                         fi
10438                         full_fs="${C1}fs$SEP3${C2} $full_fs "
10439
10440                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
10441                                 if [[ -n ${a_partition_working[6]} ]];then
10442                                         if [[ -z $( grep -E '(^//|:/|non-dev)' <<< ${a_partition_working[6]} ) ]];then
10443                                                 part_dev="/dev/${a_partition_working[6]}"
10444                                                 dev_remote='dev'
10445                                         elif [[ -n $( grep '^non-dev' <<< ${a_partition_working[6]} ) ]];then
10446                                                 holder=$( sed 's/non-dev-//' <<< ${a_partition_working[6]} )
10447                                                 part_dev="$holder"
10448                                                 dev_remote='raid'
10449                                         else
10450                                                 part_dev="${a_partition_working[6]}"
10451                                                 dev_remote='remote'
10452                                         fi
10453                                 else
10454                                         dev_remote='dev'
10455                                         part_dev='N/A'
10456                                 fi
10457                                 full_dev="${C1}$dev_remote$SEP3${C2} $part_dev "
10458                                 if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then
10459                                         if [[ -n ${a_partition_working[7]} ]];then
10460                                                 part_label="${a_partition_working[7]}"
10461                                         else
10462                                                 part_label='N/A'
10463                                         fi
10464                                         full_label="${C1}label$SEP3${C2} $part_label "
10465                                 fi
10466                                 if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then
10467                                         if [[ -n ${a_partition_working[8]} ]];then
10468                                                 part_uuid="${a_partition_working[8]}"
10469                                         else
10470                                                 part_uuid='N/A'
10471                                         fi
10472                                         full_uuid="${C1}uuid$SEP3${C2} $part_uuid"
10473                                 fi
10474                         fi
10475                         # don't show user names in output
10476                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
10477                                 partitionIdClean=$( sed $SED_RX "s|/home/([^/]+)/(.*)|/home/$FILTER_STRING/\2|" <<< ${a_partition_working[0]} )
10478                         else
10479                                 partitionIdClean=${a_partition_working[0]}
10480                         fi
10481                         id_size_fs="${C1}ID:${C2} $partitionIdClean ${C1}size$SEP3${C2} ${a_partition_working[1]} $partition_used$full_fs$full_dev"
10482                         label_uuid="$full_label$full_uuid"
10483                         # label/uuid always print one per line, so only wrap if it's very long
10484                         if [[ $B_SHOW_UUIDS == 'true' && $B_SHOW_LABELS == 'true' && $( calculate_line_length "$id_size_fs$label_uuid" ) -gt $line_max_label_uuid ]];then
10485                                 a_partition_data[$counter]="$id_size_fs"
10486                                 ((counter++))
10487                                 a_partition_data[$counter]="$label_uuid"
10488                         else
10489                                 a_partition_data[$counter]="${a_partition_data[$counter]}$id_size_fs$label_uuid"
10490                         fi
10491                         # because these lines can vary widely, using dynamic length handling here
10492                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]] || [[ $( calculate_line_length "${a_partition_data[$counter]}" ) -gt $line_max ]];then
10493                                 ((counter++))
10494                         fi
10495                 fi
10496         done
10497         # print out all lines, line starter on first line
10498         for (( i=0; i < ${#a_partition_data[@]};i++ ))
10499         do
10500                 if [[ $i -eq 0 ]];then
10501                         line_starter='Partition:'
10502                 else
10503                         line_starter=' '
10504                 fi
10505                 partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" )
10506                 print_screen_output "$partition_data"
10507         done
10508         
10509         eval $LOGFE
10510 }
10511
10512 print_program_version()
10513 {
10514         local patch_version_number=$( get_patch_version_string )
10515         local program_version="${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$patch_version_number${CN}"
10516         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
10517         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
10518         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
10519         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
10520         #local line_max=$COLS_INNER
10521         #program_version="$( sed -e :a -e "s/^.\{1,$line_max\}$/ &/;ta" <<< $program_version )" # use to create padding if needed
10522         # program_version=$( create_print_line "Version:" "$program_version" )
10523         print_screen_output "$program_version"
10524 }
10525
10526 print_ps_data()
10527 {
10528         eval $LOGFS
10529         
10530         local b_print_first='true' 
10531
10532         if [[ $B_SHOW_PS_CPU_DATA == 'true' ]];then
10533                 get_ps_tcm_data 'cpu'
10534                 print_ps_item 'cpu' "$b_print_first"
10535                 b_print_first='false' 
10536         fi
10537         if [[ $B_SHOW_PS_MEM_DATA == 'true' ]];then
10538                 get_ps_tcm_data 'mem'
10539                 print_ps_item 'mem' "$b_print_first"
10540         fi
10541         
10542         eval $LOGFE
10543 }
10544
10545 # args: $1 - cpu/mem; $2 true/false
10546 print_ps_item()
10547 {
10548         eval $LOGFS
10549         local a_ps_data='' ps_data='' line_starter='' line_start_data='' full_line=''
10550         local app_name='' app_pid='' app_cpu='' app_mem='' throttled='' app_daemon=''
10551         local b_print_first=$2 line_counter=0 i=0 count_nu='' extra_data=''
10552         
10553         if [[ -n $PS_THROTTLED ]];then
10554                 throttled=" ${C1} - throttled from${C2} $PS_THROTTLED"
10555         fi
10556         case $1 in
10557                 cpu)
10558                         line_start_data="${C1}CPU - % used - top ${C2} $PS_COUNT ${C1}active$throttled "
10559                         ;;
10560                 mem)
10561                         line_start_data="${C1}Memory - MB / % used - top ${C2} $PS_COUNT ${C1}active$throttled"
10562                         ;;
10563         esac
10564         
10565         if [[ $b_print_first == 'true' ]];then
10566                 line_starter='Processes:'
10567         else
10568                 line_starter=' '
10569         fi
10570         
10571         # appName, appPath, appStarterName, appStarterPath, cpu, mem, pid, vsz, user
10572         ps_data=$( create_print_line "$line_starter" "$line_start_data" )
10573         print_screen_output "$ps_data"
10574
10575         for (( i=0; i < ${#A_PS_DATA[@]}; i++ ))
10576         do
10577                 IFS=","
10578                 a_ps_data=(${A_PS_DATA[i]})
10579                 IFS="$ORIGINAL_IFS"
10580                 
10581                 # handle the converted app names, with ~..~ means it didn't have a path
10582                 if [[ -n $( grep -E '^~.*~$' <<<  ${a_ps_data[0]} ) ]];then
10583                         app_daemon='daemon'
10584                 else
10585                         app_daemon='command'
10586                 fi
10587
10588                 app_name=" ${C1}$app_daemon$SEP3${C2} ${a_ps_data[0]}"
10589                 if [[ ${a_ps_data[0]} != ${a_ps_data[2]} ]];then
10590                         app_name="$app_name ${C1}(started by$SEP3${C2} ${a_ps_data[2]}${C1})${C2}"
10591                 fi
10592                 app_pid=" ${C1}pid$SEP3${C2} ${a_ps_data[6]}"
10593                 #  ${C1}user:${C2} ${a_ps_data[8]}
10594                 case $1 in
10595                         cpu)
10596                                 app_cpu=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
10597                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10598                                         extra_data=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
10599                                 fi
10600                                 ;;
10601                         mem)
10602                                 app_mem=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
10603                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10604                                         extra_data=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
10605                                 fi
10606                                 ;;
10607                 esac
10608                 (( line_counter++ ))
10609                 count_nu="${C1}$line_counter:${C2}"
10610                 full_line="$count_nu$app_cpu$app_mem$app_name$app_pid$extra_data"
10611                 ps_data=$( create_print_line " " "$full_line" )
10612                 print_screen_output "$ps_data"
10613         done
10614         
10615         eval $LOGFE
10616 }
10617
10618 print_raid_data()
10619 {
10620         eval $LOGFS
10621         local device='' device_string='' device_state='' raid_level='' device_components=''
10622         local device_report='' u_data='' blocks='' super_blocks='' algorithm='' chunk_size=''
10623         local bitmap_values='' recovery_progress_bar='' recovery_percent='' recovered_sectors=''
10624         local finish_time='' recovery_speed='' raid_counter=0 device_counter=1 basic_counter=1
10625         local a_raid_working='' raid_data='' kernel_support='' read_ahead='' unused_devices=''
10626         local basic_raid='' basic_raid_separator='' basic_raid_plural='' inactive=''
10627         local component_separator='' device_id='' print_string='' loop_limit=0 array_count_unused=''
10628         local array_count='' raid_event='' b_print_lines='true'
10629         local no_raid_detected='' dev_string='/dev/'
10630         local empty_raid_data='' report_size='report' blocks_avail='blocks' chunk_raid_usage='chunk size'
10631         
10632         if [[ -n $BSD_TYPE ]];then
10633                 no_raid_detected='No zfs software RAID detected - other types not yet supported.'
10634                 empty_raid_data='No zfs RAID data available - other types not yet supported.'
10635                 report_size='full size'
10636                 blocks_avail='available size'
10637                 chunk_raid_usage='raid allocated'
10638         else
10639                 no_raid_detected="No RAID data available - $FILE_MDSTAT is missing - is md_mod kernel module loaded?"
10640                 empty_raid_data="No RAID devices detected - $FILE_MDSTAT and md_mod kernel raid module present"
10641         fi
10642         
10643         if [[ $BSD_TYPE == 'bsd' ]];then
10644                 dev_string=''
10645         fi
10646         if [[ $B_RAID_SET != 'true' ]];then
10647                 get_raid_data
10648         fi
10649
10650         for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
10651         do
10652                 IFS=","
10653                 a_raid_working=(${A_RAID_DATA[i]})
10654                 IFS="$ORIGINAL_IFS"
10655                 
10656                 # reset on each iteration
10657                 algorithm=''
10658                 bitmap_values=''
10659                 blocks=''
10660                 component_separator=''
10661                 device=''
10662                 device_components=''
10663                 device_id=''
10664                 device_report=''
10665                 device_state=''
10666                 failed=''
10667                 finish_time=''
10668                 inactive=''
10669                 raid_event=''
10670                 raid_level=''
10671                 recovery_percent=''
10672                 recovery_progress_bar=''
10673                 recovered_sectors=''
10674                 recovery_speed=''
10675                 spare=''
10676                 super_blocks=''
10677                 u_data=''
10678                 
10679                 if [[ -n $( grep '^md' <<< ${a_raid_working[0]} ) && -z $BSD_TYPE ]] || \
10680                 [[ -n $BSD_TYPE && ${a_raid_working[0]} != '' ]];then
10681                         if [[ $B_SHOW_BASIC_RAID == 'true' ]];then
10682                                 if [[ $basic_raid != '' ]];then
10683                                         basic_raid_plural='s'
10684                                 fi
10685                                 if [[ ${a_raid_working[1]} == 'inactive' ]];then
10686                                         inactive=" - ${a_raid_working[1]}"
10687                                 fi
10688                                 basic_raid="$basic_raid$basic_raid_separator${C1}$basic_counter${SEP3}${C2} $dev_string${a_raid_working[0]}$inactive"
10689                                 basic_raid_separator=' '
10690                                 (( basic_counter++ ))
10691                         else
10692                                 device_id="-$device_counter"
10693                                 device="$dev_string${a_raid_working[0]}"
10694                                 
10695                                 (( device_counter++ ))
10696                                 if [[ ${a_raid_working[1]} != '' ]];then
10697                                         device_state=" - ${a_raid_working[1]}"
10698                                 fi
10699                                 
10700                                 if [[ ${a_raid_working[2]} == '' ]];then
10701                                         raid_level='N/A'
10702                                 else
10703                                         raid_level=${a_raid_working[2]}
10704                                 fi
10705                                 # there's one case: md0 : inactive  that has to be protected against
10706                                 if [[ ${a_raid_working[2]} == '' && ${a_raid_working[1]} == 'inactive' ]];then
10707                                         raid_level=''
10708                                 else
10709                                         raid_level=" ${C1}raid${SEP3}${C2} $raid_level"
10710                                 fi
10711                                 if [[ ${a_raid_working[4]} != '' ]];then
10712                                         device_report="${a_raid_working[4]}"
10713                                 else
10714                                         device_report="N/A"
10715                                 fi
10716                                 if [[ $B_EXTRA_DATA == 'true' ]];then
10717                                         if [[ ${a_raid_working[6]} != '' ]];then
10718                                                 blocks=${a_raid_working[6]}
10719                                         else
10720                                                 blocks='N/A'
10721                                         fi
10722                                         blocks=" ${C1}$blocks_avail${SEP3}${C2} $blocks"
10723                                         
10724                                         if [[ ${a_raid_working[9]} != '' ]];then
10725                                                 chunk_size=${a_raid_working[9]}
10726                                         else
10727                                                 chunk_size='N/A'
10728                                         fi
10729                                         chunk_size=" ${C1}$chunk_raid_usage${SEP3}${C2} $chunk_size"
10730                                         if [[ ${a_raid_working[10]} != '' ]];then
10731                                                 bitmap_value='true'
10732                                                 bitmap_value=" ${C1}bitmap${SEP3}${C2} $bitmap_value"
10733                                         fi
10734                                 fi
10735                                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10736                                         if [[ ${a_raid_working[5]} != '' ]];then
10737                                                 u_data=" ${a_raid_working[5]}"
10738                                         fi
10739                                         if [[ ${a_raid_working[7]} != '' ]];then
10740                                                 super_blocks=" ${C1}super blocks${SEP3}${C2} ${a_raid_working[7]}"
10741                                         fi
10742                                         if [[ ${a_raid_working[8]} != '' ]];then
10743                                                 algorithm=" ${C1}algorithm${SEP3}${C2} ${a_raid_working[8]}"
10744                                         fi
10745                                 fi
10746                                 if [[ ${a_raid_working[3]} == '' ]];then
10747                                         if [[ ${a_raid_working[1]} != 'inactive' ]];then
10748                                                 device_components='N/A'
10749                                         fi
10750                                 else
10751                                         for component in ${a_raid_working[3]}
10752                                         do
10753                                                 if [[ $B_EXTRA_DATA != 'true' ]];then
10754                                                         component=$( sed 's/\[[0-9]\+\]//' <<< $component )
10755                                                 fi
10756                                                 # NOTE: for bsd zfs, states are: ONLINE,DEGRADED,OFFLINE (at least)
10757                                                 if [[ -n $( grep -E '(F|DEGRADED)' <<< $component ) ]];then
10758                                                         component=$( sed -e 's/(F)//' -e 's/F//' -e 's/DEGRADED//' <<<  $component )
10759                                                         failed="$failed $component"
10760                                                         component=''
10761                                                 elif [[ -n $( grep -E '(S|OFFLINE)' <<< $component ) ]];then
10762                                                         component=$( sed -e 's/(S)//' -e 's/S//' -e 's/OFFLINE//' <<<  $component )
10763                                                         spare="$spare $component"
10764                                                         component=''
10765                                                 else
10766                                                         device_components="$device_components$component_separator$component"
10767                                                         component_separator=' '
10768                                                 fi
10769                                         done
10770
10771                                         if [[ $failed != '' ]];then
10772                                                 failed=" ${C1}FAILED${SEP3}${C2}$failed${C2}"
10773                                         fi
10774                                         if [[ $spare != '' ]];then
10775                                                 spare=" ${C1}spare${SEP3}${C2}$spare${C2}"
10776                                         fi
10777                                         
10778                                         if [[ -n $device_components || -n $spare || -n $failed ]];then
10779                                                 if [[ $B_EXTRA_DATA != 'true' && -z $BSD_TYPE ]];then
10780                                                         if [[ $device_report != 'N/A' && -n $device_components ]];then
10781                                                                 device_components="$device_report - $device_components"
10782                                                         fi
10783                                                 fi
10784                                                 if [[ $device_components == '' ]];then
10785                                                         device_components='none'
10786                                                 fi
10787                                                 device_components="${C1}online${SEP3}${C2} $device_components"
10788                                                 device_components=" ${C1}components${SEP3}${C2} $device_components$failed$spare"
10789                                         fi
10790                                 fi
10791                                 a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$raid_level$device_components"
10792                                 
10793                                 if [[ $B_EXTRA_DATA == 'true' && ${a_raid_working[1]} != 'inactive' ]];then
10794                                         a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$device_components"
10795                                         (( raid_counter++ ))
10796                                         print_string="${C1}Info${SEP3}${C2}$raid_level ${C1}$report_size${SEP3}${C2} $device_report$u_data"
10797                                         print_string="$print_string$blocks$chunk_size$bitmap_value$super_blocks$algorithm"
10798                                         a_raid_data[$raid_counter]="$print_string"
10799                                 else
10800                                         a_raid_data[$raid_counter]="${C1}Device$device_id${SEP3}${C2} $device$device_state$raid_level$device_components"
10801                                 fi
10802                                 (( raid_counter++ ))
10803                                 
10804                                 # now let's do the recover line if required
10805                                 if [[ ${a_raid_working[12]} != '' ]];then
10806                                         recovery_percent=$( cut -d '~' -f 2 <<< ${a_raid_working[12]} )
10807                                         if [[ ${a_raid_working[14]} != '' ]];then
10808                                                 finish_time=${a_raid_working[14]}
10809                                         else
10810                                                 finish_time='N/A'
10811                                         fi
10812                                         finish_time=" ${C1}time remaining${SEP3}${C2} $finish_time"
10813                                         if [[ $B_EXTRA_DATA == 'true' ]];then
10814                                                 if [[ ${a_raid_working[13]} != '' ]];then
10815                                                         recovered_sectors=" ${C1}sectors${SEP3}${C2} ${a_raid_working[13]}"
10816                                                 fi
10817                                         fi
10818                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
10819                                                 if [[ ${a_raid_working[11]} != '' ]];then
10820                                                         recovery_progress_bar=" ${a_raid_working[11]}"
10821                                                 fi
10822                                                 if [[ ${a_raid_working[15]} != '' ]];then
10823                                                         recovery_speed=" ${C1}speed${SEP3}${C2} ${a_raid_working[15]}"
10824                                                 fi
10825                                         fi
10826                                         
10827                                         a_raid_data[$raid_counter]="${C1}Recovering${SEP3}${C2} $recovery_percent$recovery_progress_bar$recovered_sectors$finish_time$recovery_speed"
10828                                         (( raid_counter++ ))
10829                                 fi
10830                         fi
10831                 elif [[ ${a_raid_working[0]} == 'KernelRaidSupport' ]];then
10832                         if [[ ${a_raid_working[1]} == '' ]];then
10833                                 kernel_support='N/A'
10834                         else
10835                                 kernel_support=${a_raid_working[1]}
10836                         fi
10837                         kernel_support=" ${C1}supported${SEP3}${C2} $kernel_support"
10838                 elif [[ ${a_raid_working[0]} == 'ReadAhead' ]];then
10839                         if [[ ${a_raid_working[1]} != '' ]];then
10840                                 read_ahead=${a_raid_working[1]}
10841                                 read_ahead=" ${C1}read ahead${SEP3}${C2} $read_ahead"
10842                         fi
10843                 elif [[ ${a_raid_working[0]} == 'UnusedDevices' ]];then
10844                         if [[ ${a_raid_working[1]} == '' ]];then
10845                                 unused_devices='N/A'
10846                         else
10847                                 unused_devices=${a_raid_working[1]}
10848                         fi
10849                         unused_devices="${C1}Unused Devices${SEP3}${C2} $unused_devices"
10850                 elif [[ ${a_raid_working[0]} == 'raidEvent' ]];then
10851                         if [[ ${a_raid_working[1]} != '' ]];then
10852                                 raid_event=${a_raid_working[1]}
10853                                 raid_event=" ${C1}Raid Event${SEP3}${C2} ${a_raid_working[1]}"
10854                         fi
10855                 fi
10856         done
10857         
10858         if [[ $B_SHOW_BASIC_RAID == 'true' && $basic_raid != '' ]];then
10859                 a_raid_data[0]="${C1}Device$basic_raid_plural${SEP3}${C2} $basic_raid"
10860         fi
10861         # note bsd temp test hack to make it run
10862         if [[ $B_MDSTAT_FILE != 'true' && -z $BSD_TYPE ]] || \
10863         [[ -n $BSD_TYPE && $B_BSD_RAID == 'false' ]];then
10864                 if [[ $B_SHOW_RAID_R == 'true' ]];then
10865                         a_raid_data[0]="$no_raid_detected"
10866                 else
10867                         b_print_lines='false'
10868                 fi
10869         else
10870                 if [[ ${a_raid_data[0]} == '' ]];then
10871                         if [[ $B_SHOW_BASIC_RAID != 'true' ]];then
10872                                 a_raid_data[0]="$empty_raid_data"
10873                         else
10874                                 b_print_lines='false'
10875                         fi
10876                 fi
10877                 # now let's add on the system line and the unused device line. Only print on -xx
10878                 if [[ $kernel_support$read_ahead$raid_event != '' ]];then
10879                         array_count=${#a_raid_data[@]}
10880                         a_raid_data[array_count]="${C1}System${SEP3}${C2}$kernel_support$read_ahead$raid_event"
10881                         loop_limit=1
10882                 fi
10883                 if [[ $unused_devices != '' ]];then
10884                         array_count_unused=${#a_raid_data[@]}
10885                         a_raid_data[array_count_unused]="$unused_devices"
10886                         loop_limit=2
10887                 fi
10888         fi
10889
10890         # we don't want to print anything if it's -b and no data is present, just a waste of a line
10891         if [[ $b_print_lines == 'true' ]];then
10892                 # print out all lines, line starter on first line
10893                 for (( i=0; i < ${#a_raid_data[@]} - $loop_limit;i++ ))
10894                 do
10895                         if [[ $i -eq 0 ]];then
10896                                 line_starter='RAID:'
10897                         else
10898                                 line_starter=' '
10899                         fi
10900                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count != '' ]];then
10901                                 if [[ $i == 0 ]];then
10902                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count]}" )
10903                                         print_screen_output "$raid_data"
10904                                         line_starter=' '
10905                                 fi
10906                         fi
10907                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[i]}" )
10908                         print_screen_output "$raid_data"
10909                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && $array_count_unused != '' ]];then
10910                                 if [[ $i == $(( array_count_unused - 2 )) ]];then
10911                                         raid_data=$( create_print_line "$line_starter" "${a_raid_data[array_count_unused]}" )
10912                                         print_screen_output "$raid_data"
10913                                 fi
10914                         fi
10915                 done
10916         fi
10917         
10918         eval $LOGFE
10919 }
10920
10921 # currently only apt using distros support this feature, but over time we can add others
10922 print_repo_data()
10923 {
10924         eval $LOGFS
10925         local repo_count=0 repo_line='' file_name='' file_content='' file_name_holder=''
10926         local repo_full='' b_print_next_line='false' repo_type=''
10927         
10928         get_repo_data
10929         
10930         if [[ -n $REPO_DATA ]];then
10931                 # loop through the variable's lines one by one, update counter each iteration
10932                 while read repo_line
10933                 do
10934                         (( repo_count++ ))
10935                         repo_type=$( cut -d ':' -f 1 <<< $repo_line )
10936                         file_name=$( cut -d ':' -f 2 <<< $repo_line )
10937                         file_content=$( cut -d ':' -f 3-7 <<< $repo_line )
10938                         # this will dump unwanted white space line starters. Some irc channels
10939                         # use bots that show page title for urls, so need to break the url by adding 
10940                         # a white space.
10941                         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
10942                                 file_content=$( echo $file_content | sed 's|://|: //|' )
10943                         else
10944                                 file_content=$( echo $file_content )
10945                         fi
10946                         # echo $file_name : $file_name_holder : $repo_type : $file_content
10947                         # check file name, if different, update the holder for print out
10948                         if [[ $file_name != $file_name_holder ]];then
10949                                 if [[ $repo_type == 'pisi repo' || $repo_type == 'urpmq repo' ]];then
10950                                         repo_full="${C1}$repo_type:${C2} $file_name"
10951                                 else
10952                                         repo_full="${C1}Active $repo_type in file:${C2} $file_name"
10953                                 fi
10954                                 file_name_holder=$file_name
10955                                 b_print_next_line='true'
10956                         else
10957                                 repo_full=$file_content
10958                         fi
10959                         # first line print Repos: 
10960                         if [[ $repo_count -eq 1 ]];then
10961                                 repo_full=$( create_print_line "Repos:" "$repo_full" )
10962                         else
10963                                 repo_full=$( create_print_line " " "$repo_full" )
10964                         fi
10965                         print_screen_output "$repo_full"
10966                         # this prints the content of the file as well as the file name
10967                         if [[ $b_print_next_line == 'true' ]];then
10968                                 repo_full=$( create_print_line " " "$file_content" )
10969                                 print_screen_output "$repo_full"
10970                                 b_print_next_line='false'
10971                         fi
10972                 done <<< "$REPO_DATA"
10973         else
10974                 repo_full=$( create_print_line "Repos:" "${C1}Error:${C2} $SCRIPT_NAME does not support this feature for your distro yet." )
10975                 print_screen_output "$repo_full"
10976         fi
10977         eval $LOGFE
10978 }
10979
10980 print_sensors_data()
10981 {
10982         eval $LOGFS
10983         local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' 
10984         local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp=''
10985         local a_sensors_working=''
10986         local no_sensors_message='None detected - is lm-sensors installed and configured?'
10987         local Sensors_Data="$( get_sensors_output )"
10988         get_sensors_data
10989         
10990         if [[ $BSD_TYPE == 'bsd' ]];then
10991                 no_sensors_message='This feature is not yet supported for BSD systems.'
10992         fi
10993         
10994         IFS=","
10995         a_sensors_working=( ${A_SENSORS_DATA[0]} )
10996         IFS="$ORIGINAL_IFS"
10997         # initial error cases, for missing app or unconfigured sensors. Note that array 0
10998         # always has at least 3 items, cpu/mobo/psu temp in it. If the count is 0, then
10999         # no sensors are installed/configured
11000         if [[ ${#a_sensors_working[@]} -eq 0 ]];then
11001                 cpu_temp=$no_sensors_message
11002                 b_is_error='true'
11003         else
11004                 for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ ))
11005                 do
11006                         IFS=","
11007                         a_sensors_working=( ${A_SENSORS_DATA[i]} )
11008                         IFS="$ORIGINAL_IFS"
11009                         case $i in
11010                                 # first the temp data
11011                                 0)
11012                                         if [[ -n ${a_sensors_working[0]} ]];then
11013                                                 cpu_temp=${a_sensors_working[0]}
11014                                         else
11015                                                 cpu_temp='N/A'
11016                                         fi
11017                                         cpu_temp="${C1}System Temperatures: cpu$SEP3${C2} $cpu_temp "
11018
11019                                         if [[ -n ${a_sensors_working[1]} ]];then
11020                                                 mobo_temp=${a_sensors_working[1]}
11021                                         else
11022                                                 mobo_temp='N/A'
11023                                         fi
11024                                         mobo_temp="${C1}mobo$SEP3${C2} $mobo_temp "
11025
11026                                         if [[ -n ${a_sensors_working[2]} ]];then
11027                                                 psu_temp="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
11028                                         fi
11029                                         gpu_temp=$( get_gpu_temp_data )
11030                                         # dump the unneeded screen data for single gpu systems 
11031                                         if [[ $( wc -w <<< $gpu_temp ) -eq 1 && $B_EXTRA_DATA != 'true' ]];then
11032                                                 gpu_temp=$( cut -d ':' -f 2 <<< $gpu_temp )
11033                                         fi
11034                                         if [[ -n $gpu_temp ]];then
11035                                                 gpu_temp="${C1}gpu$SEP3${C2} ${gpu_temp} "
11036                                         fi
11037                                         ;;
11038                                 # then the fan data from main fan array
11039                                 1)
11040                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
11041                                         do
11042                                                 case $j in
11043                                                         0)
11044                                                                 # we need to make sure it's either cpu fan OR cpu fan and sys fan 1
11045                                                                 if [[ -n ${a_sensors_working[0]} ]];then
11046                                                                         cpu_fan="${a_sensors_working[0]}"
11047                                                                 elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then
11048                                                                         cpu_fan="${a_sensors_working[1]}"
11049                                                                 else
11050                                                                         cpu_fan='N/A'
11051                                                                 fi
11052                                                                 cpu_fan="${C1}Fan Speeds (in rpm): cpu$SEP3${C2} $cpu_fan "
11053                                                                 (( fan_count++ ))
11054                                                                 ;;
11055                                                         1)
11056                                                                 if [[ -n ${a_sensors_working[1]} ]];then
11057                                                                         mobo_fan="${C1}mobo$SEP3${C2} ${a_sensors_working[1]} "
11058                                                                         (( fan_count++ ))
11059                                                                 fi
11060                                                                 ;;
11061                                                         2)
11062                                                                 if [[ -n ${a_sensors_working[2]} ]];then
11063                                                                         ps_fan="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
11064                                                                         (( fan_count++ ))
11065                                                                 fi
11066                                                                 ;;
11067                                                         [3-9]|[1-9][0-9])
11068                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
11069                                                                         fan_number=$(( $j - 2 )) # sys fans start on array key 5
11070                                                                         # wrap after fan 6 total
11071                                                                         if [[ $fan_count -lt 7 ]];then
11072                                                                                 sys_fans="$sys_fans${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11073                                                                         else
11074                                                                                 sys_fans2="$sys_fans2${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11075                                                                         fi
11076                                                                         (( fan_count++ ))
11077                                                                 fi
11078                                                                 ;;
11079                                                 esac
11080                                         done
11081                                         ;;
11082                                 2)
11083                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
11084                                         do
11085                                                 case $j in
11086                                                         [0-9]|[1-9][0-9])
11087                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
11088                                                                         fan_number=$(( $j + 1 )) # sys fans start on array key 5
11089                                                                         # wrap after fan 6 total
11090                                                                         if [[ $fan_count -lt 7 ]];then
11091                                                                                 sys_fans="$sys_fans${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11092                                                                         else
11093                                                                                 sys_fans2="$sys_fans2${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
11094                                                                         fi
11095                                                                         (( fan_count++ ))
11096                                                                 fi
11097                                                                 ;;
11098                                                 esac
11099                                         done
11100                                         ;;
11101                         esac
11102                 done
11103         fi
11104         # turning off all output for case where no sensors detected or no sensors output 
11105         # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used
11106         if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then
11107                 temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp"
11108                 temp_data=$( create_print_line "Sensors:" "$temp_data" )
11109                 print_screen_output "$temp_data"
11110                 # don't print second or subsequent lines if error data
11111                 fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans"
11112                 if [[ $b_is_error != 'true' && -n $fan_data ]];then
11113                         fan_data=$( create_print_line " " "$fan_data" )
11114                         print_screen_output "$fan_data"
11115                         # and then second wrapped fan line if needed
11116                         if [[ -n $sys_fans2 ]];then
11117                                 fan_data2=$( create_print_line " " "$sys_fans2" )
11118                                 print_screen_output "$fan_data2"
11119                         fi
11120                 fi
11121         fi
11122         eval $LOGFE
11123 }
11124
11125 print_system_data()
11126 {
11127         eval $LOGFS
11128         local system_data='' bits='' desktop_environment='' dm_data='' de_extra_data=''
11129         local host_kernel_string='' de_distro_string='' host_string='' desktop_type='Desktop'
11130         local host_name=$HOSTNAME
11131         local current_kernel=$( get_kernel_version ) 
11132         local distro="$( get_distro_data )"
11133         local tty_session=''
11134         
11135         # I think these will work, maybe, if logged in as root and in X
11136         if [[ $B_RUNNING_IN_DISPLAY == 'true' ]];then
11137                 desktop_environment=$( get_desktop_environment )
11138                 if [[ -z $desktop_environment ]];then
11139                         desktop_environment='N/A'
11140                 fi
11141                 
11142                 if [[  $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
11143                         de_extra_data=$( get_desktop_extra_data )
11144                         if [[ -n $de_extra_data ]];then
11145                                 de_extra_data=" ${C1}info$SEP3${C2} $de_extra_data"
11146                         fi
11147                 fi
11148         else
11149                 tty_session=$( get_tty_number )
11150                 if [[ -z $tty_session && $B_CONSOLE_IRC == 'true' ]];then
11151                         tty_session=$( get_tty_console_irc )
11152                 fi
11153                 if [[ -n $tty_session ]];then
11154                         tty_session=" $tty_session"
11155                 fi
11156                 desktop_environment="tty$tty_session"
11157                 desktop_type='Console'
11158         fi
11159         # having dm type can be useful if you are accessing remote system
11160         # or are out of X and don't remember which dm is running the system
11161         if [[  $B_EXTRA_EXTRA_DATA == 'true' ]];then
11162                 dm_data=$( get_display_manager )
11163                 # here we only want the dm info to show N/A if in X
11164                 if [[ -z $dm_data && $B_RUNNING_IN_DISPLAY == 'true' ]];then
11165                         dm_data='N/A'
11166                 fi
11167                 # only print out of X if dm_data has info, then it's actually useful, but
11168                 # for headless servers, no need to print dm stuff.
11169                 if [[ -n $dm_data ]];then
11170                         dm_data=" ${C1}dm$SEP3${C2} $dm_data"
11171                 fi
11172         fi
11173         
11174         de_distro_string="${C1}$desktop_type$SEP3${C2} $desktop_environment$de_extra_data$dm_data ${C1}Distro$SEP3${C2} $distro"
11175         if [[ $B_EXTRA_DATA == 'true' ]];then
11176                 gcc_string=$( get_gcc_kernel_version )
11177                 if [[ -n $gcc_string ]];then
11178                         gcc_string=", ${C1}gcc$SEP3${C2} $gcc_string"
11179                 fi
11180         fi
11181         # check for 64 bit first
11182         if [[ -n $( uname -m | grep -E '(x86_64|amd64)' ) ]];then
11183                 bits="64"
11184         else
11185                 bits="32"
11186         fi
11187         bits=" (${bits} bit${gcc_string})"
11188         if [[ $B_SHOW_HOST == 'true' ]];then
11189                 if [[ -z $HOSTNAME ]];then
11190                         if [[ -n $( type p hostname ) ]];then
11191                                 host_name=$( hostname )
11192                         fi
11193                         if [[ -z $host_name ]];then
11194                                 host_name='N/A'
11195                         fi
11196                 fi
11197                 host_string="${C1}Host$SEP3${C2} $host_name "
11198                 system_data=$( create_print_line "System:" "$host_string$host_name ${C1}Kernel$SEP3${C2}" )
11199         fi
11200         host_kernel_string="$host_string${C1}Kernel$SEP3${C2} $current_kernel$bits "
11201         if [[ $( calculate_line_length "$host_kernel_string$de_distro_string" ) -lt $COLS_INNER ]];then
11202                 system_data="$host_kernel_string$de_distro_string"
11203                 system_data=$( create_print_line "System:" "$system_data" )
11204         else
11205                 system_data=$( create_print_line "System:" "$host_kernel_string" )
11206                 print_screen_output "$system_data"
11207                 system_data=$( create_print_line " " "$de_distro_string" )
11208         fi
11209         print_screen_output "$system_data"
11210         eval $LOGFE
11211 }
11212
11213 print_unmounted_partition_data()
11214 {
11215         eval $LOGFS
11216         local a_unmounted_data='' line_starter='' unmounted_data='' full_fs=''
11217         local full_dev='' full_size='' full_label='' full_uuid='' full_string=''
11218         local bsd_unsupported='This feature is not yet supported for BSD systems.'
11219         
11220         if [[ -z ${A_PARTITION_DATA} ]];then
11221                 get_partition_data
11222         fi
11223         get_unmounted_partition_data
11224         
11225         if [[ ${#A_UNMOUNTED_PARTITION_DATA[@]} -ge 1 ]];then
11226                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
11227                 do
11228                         IFS=","
11229                         a_unmounted_data=(${A_UNMOUNTED_PARTITION_DATA[i]})
11230                         IFS="$ORIGINAL_IFS"
11231                         if [[ -z ${a_unmounted_data[0]} ]];then
11232                                 full_dev='N/A'
11233                         else
11234                                 full_dev="/dev/${a_unmounted_data[0]}"
11235                         fi
11236                         full_dev="${C1}ID:${C2} $full_dev"
11237                         if [[ -z ${a_unmounted_data[1]} ]];then
11238                                 full_size='N/A'
11239                         else
11240                                 full_size=${a_unmounted_data[1]}
11241                         fi
11242                         full_size="${C1}size$SEP3${C2} $full_size"
11243                         if [[ -z ${a_unmounted_data[2]} ]];then
11244                                 full_label='N/A'
11245                         else
11246                                 full_label=${a_unmounted_data[2]}
11247                         fi
11248                         full_label="${C1}label$SEP3${C2} $full_label"
11249                         if [[ -z ${a_unmounted_data[3]} ]];then
11250                                 full_uuid='N/A'
11251                         else
11252                                 full_uuid=${a_unmounted_data[3]}
11253                         fi
11254                         full_uuid="${C1}uuid$SEP3${C2} $full_uuid"
11255                         if [[ -z ${a_unmounted_data[4]} ]];then
11256                                 full_fs=''
11257                         else
11258                                 full_fs="${C1}fs$SEP3${C2} ${a_unmounted_data[4]}"
11259                         fi
11260                         full_string="$full_dev $full_size $full_label $full_uuid $full_fs"
11261                         if [[ $i -eq 0 ]];then
11262                                 line_starter='Unmounted:'
11263                         else
11264                                 line_starter=' '
11265                         fi
11266                         # temporary message to indicate not yet supported
11267                         if [[ $BSD_TYPE == 'bsd' ]];then
11268                                 full_string=$bsd_unsupported
11269                         fi
11270                         unmounted_data=$( create_print_line "$line_starter" "$full_string" )
11271                         print_screen_output "$unmounted_data"
11272                 done
11273         else
11274                 unmounted_data=$( create_print_line "Unmounted:" "No unmounted partitions detected" )
11275                 print_screen_output "$unmounted_data"
11276         fi
11277         
11278         eval $LOGFE
11279 }
11280
11281 print_weather_data()
11282 {
11283         eval $LOGFS
11284         
11285         local weather_data='' location_string='' local_time='' time_string='' pressure=''
11286         local a_location='' a_weather='' weather_string='' weather='' temp='' winds='' humidity=''
11287         local time_zone='' observation_time='' city='' state='' country='' altitude=''
11288         local heat_index="" wind_chill='' dewpoint='' xxx_humidity=''
11289         local openP='(' closeP=')'
11290         
11291         if [[ $B_RUNNING_IN_SHELL == 'false' ]];then
11292                 openP=''
11293                 closeP=''
11294         fi
11295         
11296         get_weather_data
11297         
11298         # city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3 
11299         #  ";" latitude "," longitude ";" postalCode ";" timeZone
11300         
11301         # observationTime ";" localTime ";" weather ";" tempString ";" humidity 
11302         # ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
11303         # ";" windChillString ";" siteElevation
11304
11305         if [[ ${#A_WEATHER_DATA[@]} -eq 2 ]];then
11306                 IFS=";"
11307                 a_location=(${A_WEATHER_DATA[0]})
11308                 a_weather=(${A_WEATHER_DATA[1]})
11309                 IFS="$ORIGINAL_IFS"
11310                 
11311                 if [[ -n ${a_weather[3]} ]];then
11312                         temp=${a_weather[3]}
11313                 else
11314                         temp='N/A'
11315                 fi
11316                 if [[ -n ${a_weather[2]} ]];then
11317                         weather=" - ${a_weather[2]}"
11318                 else
11319                         weather=''
11320                 fi
11321                 if [[ $B_EXTRA_DATA == 'true' ]];then
11322                         if [[ -n ${a_weather[5]} ]];then
11323                                 winds=" ${C1}Wind$SEP3${C2} ${a_weather[5]}"
11324                         fi
11325                 fi
11326                 if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
11327                         if [[ -n ${a_weather[4]} ]];then
11328                                 humidity=" ${C1}Humidity$SEP3${C2} ${a_weather[4]}"
11329                         fi
11330                         if [[ -n ${a_weather[6]} ]];then
11331                                 pressure="${C1}Pressure$SEP3${C2} ${a_weather[6]} "
11332                         fi
11333                 fi
11334                 weather_string="${C1}Conditions$SEP3${C2} $temp$weather$winds$humidity"
11335                 
11336                 if [[ -n ${a_weather[1]} ]];then
11337                         local_time=" ${a_weather[1]}"
11338                 else
11339                         local_time=" $(date)"
11340                 fi
11341                 if [[ $B_EXTRA_DATA == 'true' && -n ${a_location[8]} ]];then
11342                         time_zone=" (${a_location[8]})"
11343                 fi
11344                 time_string="${C1}Time$SEP3${C2}$local_time$time_zone"
11345
11346                 if [[ $B_EXTRA_DATA != 'true' ]];then
11347                         weather_data="$weather_string $time_string"
11348                         weather_data=$( create_print_line "Weather:" "$weather_data" )
11349                         print_screen_output "$weather_data"
11350                 else
11351                         weather_data="$weather_string"
11352                         weather_data=$( create_print_line "Weather:" "$weather_data" )
11353                         print_screen_output "$weather_data"
11354                         if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
11355                                 if [[ -n ${a_weather[8]} ]];then
11356                                         heat_index="${C1}Heat Index$SEP3${C2} ${a_weather[8]} "
11357                                 fi
11358                                 if [[ -n ${a_weather[9]} ]];then
11359                                         wind_chill="${C1}Wind Chill$SEP3${C2} ${a_weather[9]} "
11360                                 fi
11361                                 if [[ -n ${a_weather[7]} ]];then
11362                                         dew_point="${C1}Dew Point$SEP3${C2} ${a_weather[7]} "
11363                                 fi
11364                                 if [[ -n ${a_weather[0]} ]];then
11365                                         observation_time=" ${C1}Observation Time$SEP3${C2} ${a_weather[0]} "
11366                                 fi
11367                                 if [[ $B_OUTPUT_FILTER != 'true' ]];then
11368                                         if [[ -n ${a_location[0]} ]];then
11369                                                 city=" ${a_location[0]}"
11370                                         fi
11371                                         if [[ -n ${a_location[1]} ]];then
11372                                                 state=" ${a_location[1]}"
11373                                         fi
11374                                         if [[ -n ${a_location[5]} ]];then
11375                                                 country=" $openP${a_location[5]}$closeP"
11376                                         fi
11377                                         if [[ -n ${a_weather[10]} ]];then
11378                                                 altitude=" ${C1}Altitude$SEP3${C2} ${a_weather[10]}"
11379                                         fi
11380                                         location_string="${C1}Location$SEP3${C2}$city$state$country$altitude "
11381                                 else
11382                                         location_string=$time_string$observation_time
11383                                         time_string=''
11384                                         observation_time=''
11385                                 fi
11386                                 # the last three are oftenblank
11387                                 if [[ -z "$heat_index$wind_chill$dew_point" ]];then
11388                                         weather_data=$( create_print_line " " "$pressure$location_string" )
11389                                         print_screen_output "$weather_data"
11390                                 else
11391                                         weather_data=$( create_print_line " " "$pressure$heat_index$wind_chill$dew_point" )
11392                                         print_screen_output "$weather_data"
11393                                         if [[ $B_OUTPUT_FILTER != 'true' ]];then
11394                                                 weather_data=$( create_print_line " " "$location_string" )
11395                                                 print_screen_output "$weather_data"
11396                                         fi
11397                                 fi
11398                                 if [[ -n $time_string$observation_time ]];then
11399                                         weather_data=$( create_print_line " " "$time_string$observation_time" )
11400                                         print_screen_output "$weather_data"
11401                                 fi
11402                         else
11403                                 if [[ -n $pressure$time_string ]];then
11404                                         weather_data="$pressure$time_string"
11405                                         weather_data=$( create_print_line " " "$weather_data" )
11406                                         print_screen_output "$weather_data"
11407                                 fi
11408                         fi
11409                 fi
11410         else
11411                 weather_data=$( create_print_line "Weather:" "Weather data failure: $(date)" )
11412                 print_screen_output "$weather_data"
11413                 weather_data=$( create_print_line " " "${A_WEATHER_DATA}" )
11414                 print_screen_output "$weather_data"
11415         fi
11416         eval $LOGFE
11417 }
11418
11419 ########################################################################
11420 #### SCRIPT EXECUTION
11421 ########################################################################
11422
11423 main $@ ## From the End comes the Beginning
11424
11425 ## note: this EOF is needed for smxi handling, this is what triggers the full download ok
11426 ###**EOF**###