Add support for DH1080 key exchange
[quassel.git] / data / scripts / inxi
1 #!/bin/bash
2 ########################################################################
3 ####  Script Name: inxi
4 ####  version: 1.7.31
5 ####  Date: March 26 2012
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 script by locsmif
16 ####  As time permits functionality improvements and recoding will occur.
17 ####
18 ####  inxi, the universal, portable, system info script 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-12 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: http://techpatterns.com/forums/about1131.html
29 ####  Script svn: http://code.google.com/p/inxi
30 ####
31 ####  This program is free software; you can redistribute it and/or modify
32 ####  it under the terms of the GNU General Public License as published by
33 ####  the Free Software Foundation; either version 3 of the License, or
34 ####  (at your option) any later version.
35 ####
36 ####  This program is distributed in the hope that it will be useful,
37 ####  but WITHOUT ANY WARRANTY; without even the implied warranty of
38 ####  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39 ####  GNU General Public License for more details.
40 ####
41 ####  You should have received a copy of the GNU General Public License
42 ####  along with this program.  If not, see <http://www.gnu.org/licenses/>.
43 ####
44 ####  If you don't understand what Free Software is, please read (or reread)
45 ####  this page: http://www.gnu.org/philosophy/free-sw.html
46 ########################################################################
47 ####  * Package names in (...) are the Debian Squeeze package name. Check your 
48 ####    distro for proper package name by doing this: which <application> 
49 ####    then find what package owns that application file. Or run --recommends
50 ####    which shows package names for Debian/Ubuntu, Arch, and Fedora/Redhat/Suse
51 ####
52 ####  DEPENDENCIES
53 ####  * bash >=3.0 (bash); df, readlink, stty, tr, uname, wc (coreutils);
54 ####    gawk (gawk); grep (grep); lspci (pciutils);
55 ####    free, ps, uptime (procps); find (findutils)
56 ####  * Also the proc filesystem should be present and mounted
57 ####  * Some features, like -M and -d will not work, or will work incompletely,
58 ####    if /sys is missing
59 ####
60 ####    Apparently unpatched bash 3.0 has arrays broken; bug reports:
61 ####    http://ftp.gnu.org/gnu/bash/bash-3.0-patches/bash30-008
62 ####    http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00144.html
63 ####  Bash 3.1 for proper array use
64 ####
65 ####    Arrays work in bash 2.05b, but "grep -Em" does not
66 ####
67 ####  RECOMMENDS (Needed to run certain features, listed by option)
68 ####  -A - for output of usb audio information: lsusb (usbutils)
69 ####  -Ax -Nx - for audio/network module version: modinfo (module-init-tools)
70 ####  -Dx - for hdd temp output (root only default): hddtemp (hddtemp)
71 ####       For user level hdd temp output: sudo (sudo)
72 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
73 ####  -G - full graphics output requires:  glxinfo (mesa-utils); xdpyinfo (X11-utils);
74 ####       xrandr (x11-xserver-utils)
75 ####  -i - IP information, local/wan - ip (iproute) legacy, not used if ip present: ifconfig (net-tools)
76 ####  -Ix - view current runlevel while not in X window system (or with -x): runlevel (sysvinit)
77 ####  -M - for older systems whose kernel does not have /sys data for machine, dmidecode (dmidecode)
78 ####  -o - for unmounted file system information in unmounted drives (root only default): file (file)
79 ####       Note: requires user action for this feature to run as user (edit /etc/sudoers file)
80 ####       For user level unmounted file system type output: sudo (sudo)
81 ####  -s   For any sensors output, fan, temp, etc: sensors (lm-sensors)
82 ####       Note: requires setup of lm-sensors (sensors-detect and adding modules/modprobe/reboot,
83 ####       and ideally, pwmconfig) prior to full output being available. 
84 ####  -S   For desktop environment, user must be in X and have xprop installed (in X11-utils)
85 ########################################################################
86 ####  CONVENTIONS:
87 ####  * Character Encoding: UTF-8 - this file contains special characters that must be opened and saved as UTF8
88 ####  * Indentation: TABS
89 ####  * Do not use `....` (back quotes), those are totally non-reabable, use $(....).
90 ####  * Do not use one liner flow controls. 
91 ####    The ONLY time you should use ';' (semi-colon) is in this single case: if [[ condition ]];then.
92 ####    Never use compound 'if': ie, if [[ condition ]] && statement.
93 ####  * Note: [[ -n $something ]] - double brackets does not require quotes for variables: ie, "$something".
94 ####  * Always use quotes, double or single, for all string values.
95 ####  * All new code/methods must be in a function.
96 ####  * For all boolean tests, use 'true' / 'false'.
97 ####    !! Do NOT use 0 or 1 unless it's a function return. 
98 ####  * Avoid complicated tests in the if condition itself.
99 ####  * To 'return' a value in a function, use 'echo <var>'.
100 ####  * For gawk: use always if ( num_of_cores > 1 ) { hanging { starter for all blocks
101 ####    This lets us use one method for all gawk structures, including BEGIN/END, if, for, etc
102 ####
103 ####  VARIABLE/FUNCTION NAMING:
104 ####  * All functions should follow standard naming--verb adjective noun. 
105 ####      ie, get_cpu_data
106 ####  * All variables MUST be initialized / declared explicitly, either top of file, for Globals, or using local
107 ####  * All variables should clearly explain what they are, except counters like i, j.
108 ####  * Each word of Bash variable must be separated by '_' (underscore) (camel form), like: cpu_data
109 ####  * Each word of Gawk variable must be like this (first word lower, following start with upper): cpuData
110 ####  * Global variables are 'UPPER CASE', at top of script.
111 ####      ie, SOME_VARIABLE=''
112 ####  * Local variables are 'lower case' and declared at the top of the function using local, always.
113 ####      ie: local some_variable=''
114 ####  * Locals that will be inherited by child functions have first char capitalized (so you know they are inherited).
115 ####      ie, Some_Variable 
116 ####  * Booleans should start with b_ (local) or B_ (global) and state clearly what is being tested.
117 ####  * Arrays should start with a_ (local) or A_ (global).
118 ####
119 ####  SPECIAL NOTES:
120 ####  * The color variable ${C2} must always be followed by a space unless you know what
121 ####    character is going to be next for certain. Otherwise irc color codes can be accidentally
122 ####    activated or altered.
123 ####  * For native script konversation support (check distro for correct konvi scripts path):
124 ####    ln -s <path to inxi> /usr/share/apps/konversation/scripts/inxi
125 ####    DCOP doesn't like \n, so avoid using it for most output unless required, as in error messages.
126 ####  * print_screen_output " " # requires space, not null, to avoid error in for example in irssi
127 ####  * For logging of array data, array must be placed into the temp_array, otherwise only the first key logs
128 ####  * In gawk search patterns, . is a wildcard EXCEPT in [0-9.] type containers, then it's a literal
129 ####    So outside of bracketed items, it must be escaped, \. but inside, no need. Outside of gawk it should 
130 ####    be escaped in search patterns if you are using it as a literal.
131 ####
132 ####  As with all 'rules' there are acceptions, these are noted where used.
133 ###################################################################################
134 ####    KDE Konversation information.  Moving from dcop(qt3/KDE3) to dbus(qt4/KDE4)
135 ###################################################################################
136 ####  * dcop and dbus   -- these talk back to Konversation from this script
137 ####  * Scripting info  -- http://konversation.berlios.de/docs/scripting.html
138 ####    -- http://www.kde.org.uk/apps/konversation/
139 ####  * dbus info       -- http://dbus.freedesktop.org/doc/dbus-tutorial.html
140 ####    view dbus info  -- https://fedorahosted.org/d-feet/
141 ####    -- or run qdbus
142 ####  * Konvi dbus/usage-- qdbus org.kde.konversation /irc say <server> <target-channel> <output>
143 ####  * Python usage    -- http://wiki.python.org/moin/DbusExamples  (just in case)
144 ####
145 ####    Because webpages come and go, the above information needs to be moved to inxi's wiki
146 ########################################################################
147 ####  Valuable Resources
148 ####  gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html
149 ########################################################################
150 ####  TESTING FLAGS
151 ####  inxi supports advanced testing triggers to do various things, using -! <arg>
152 ####  -! 1  - triggers default B_TESTING_1='true' to trigger some test or other
153 ####  -! 2  - triggers default B_TESTING_2='true' to trigger some test or other
154 ####  -! 3  - triggers B_TESTING_1='true' and B_TESTING_2='true'
155 ####  -! 10 - triggers an update from the primary dev download server instead of svn
156 ####  -! 11 - triggers an update from svn branch one - if present, of course
157 ####  -! 12 - triggers an update from svn branch two - if present, of course
158 ####  -! 13 - triggers an update from svn branch three - if present, of course
159 ####  -! 14 - triggers an update from svn branch four - if present, of course
160 ####  -! <http://......> - Triggers an update from whatever server you list.
161 ####  LOG FLAGS (logs to $HOME/.inxi/inxi.log with rotate 3 total)
162 ####  -@ 8  - Basic data logging of generated data / array values
163 ####  -@ 9  - Full logging of all data used, including cat of files and system data
164 ####  -@ 10 - Basic data logging plus color code logging
165 ########################################################################
166 #### VARIABLES
167 ########################################################################
168
169 ## NOTE: we can use hwinfo if it's available in all systems, or most, to get
170 ## a lot more data and verbosity levels going
171 # set to default LANG to avoid locales errors with , or .
172 LANG=C
173 ### Variable initializations: null values
174 CMDL_MAX=''
175 COLOR_SCHEME=''
176 # override in user config if desired, seems like less than .3 doesn't work as reliably
177 CPU_SLEEP='0.3' 
178 DEV_DISK_LABEL=''
179 DEV_DISK_UUID=''
180 FILTER_STRING='<filter>'
181 IRC_CLIENT=''
182 IRC_CLIENT_VERSION=''
183 LINE_MAX=''
184 LINE_MAX_CONSOLE='115'
185 LINE_MAX_IRC='105'
186 PS_COUNT=5
187 PS_THROTTLED=''
188 REPO_DATA=''
189 REPO_FILE_ID=''
190
191 ### primary data array holders  ## usage: 'A_<var>'
192 A_ALSA_DATA=''
193 A_AUDIO_DATA=''
194 A_CMDL=''
195 A_CPU_CORE_DATA=''
196 A_CPU_DATA=''
197 A_CPU_TYPE_PCNT_CCNT=''
198 A_DEBUG_BUFFER=''
199 A_GCC_VERSIONS=''
200 A_GFX_CARD_DATA=''
201 A_GLX_DATA=''
202 A_GRAPHIC_DRIVERS=''
203 A_HDD_DATA=''
204 A_INTERFACES_DATA=''
205 A_MACHINE_DATA=''
206 A_NETWORK_DATA=''
207 A_OPTICAL_DRIVE_DATA=''
208 A_PARTITION_DATA=''
209 A_PS_DATA=''
210 A_SENSORS_DATA=''
211 A_UNMOUNTED_PARTITION_DATA=''
212 A_X_DATA=''
213
214 ### Boolean true/false globals  ## usage: 'B_<var>'
215 # flag to allow distro maintainers to turn off update features. If false, turns off
216 # -U and -! testing/advanced update options, as well as removing the -U help menu item
217 B_ALLOW_UPDATE='true'
218 B_COLOR_SCHEME_SET='false'
219 B_CONSOLE_IRC='false'
220 # triggers full display of cpu flags
221 B_CPU_FLAGS_FULL='false'
222 # test for dbus irc client
223 B_DBUS_CLIENT='false'
224 # kde dcop
225 B_DCOP='false'
226 # Debug flood override: make 'true' to allow long debug output
227 B_DEBUG_FLOOD='false'
228 # show extra output data
229 B_EXTRA_DATA='false'
230 # triggered by -xx
231 B_EXTRA_EXTRA_DATA='false'
232 # override certain errors due to currupted data
233 B_HANDLE_CORRUPT_DATA='false'
234 B_LABEL_SET='false'
235 B_LOG_COLORS='false'
236 B_LOG_FULL_DATA='false'
237 B_OUTPUT_FILTER='false'
238 B_OVERRIDE_FILTER='false'
239 # kde qdbus
240 B_QDBUS='false'
241 B_PORTABLE='false'
242 B_ROOT='false'
243 B_RUN_COLOR_SELECTOR='false'
244 # Running in a shell? Defaults to false, and is determined later.
245 B_RUNNING_IN_SHELL='false'
246 if tty >/dev/null;then
247         B_RUNNING_IN_SHELL='true'
248 fi
249 # this sets the debug buffer
250 B_SCRIPT_UP='false'
251 B_SHOW_ADVANCED_NETWORK='false'
252 # Show sound card data
253 B_SHOW_AUDIO='false'
254 B_SHOW_BASIC_CPU='false'
255 B_SHOW_BASIC_DISK='false'
256 B_SHOW_BASIC_OPTICAL='false'
257 B_SHOW_CPU='false'
258 B_SHOW_DISK_TOTAL='false'
259 B_SHOW_DISK='false'
260 # Show full hard disk output
261 B_SHOW_FULL_HDD='false'
262 B_SHOW_FULL_OPTICAL='false'
263 B_SHOW_GRAPHICS='false'
264 # Set this to 'false' to avoid printing the hostname, this isn't used except for 
265 # user configuration options via config files
266 B_SHOW_HOST='true'
267 B_SHOW_INFO='false'
268 B_SHOW_IP='false'
269 B_SHOW_LABELS='false'
270 B_SHOW_MACHINE='false'
271 B_SHOW_NETWORK='false'
272 # either -v > 3 or -P will show partitions
273 B_SHOW_PARTITIONS='false'
274 B_SHOW_PARTITIONS_FULL='false'
275 B_SHOW_PS_CPU_DATA='false'
276 B_SHOW_PS_MEM_DATA='false'
277 B_SHOW_REPOS='false'
278 B_RUNNING_IN_X='false'
279 B_SHOW_SENSORS='false'
280 # triggers only short inxi output
281 B_SHOW_SHORT_OUTPUT='false'
282 B_SHOW_SYSTEM='false'
283 B_SHOW_UNMOUNTED_PARTITIONS='false'
284 B_SHOW_UUIDS='false'
285 B_SHOW_X_DATA='false'
286 # triggers various debugging and new option testing
287 B_TESTING_1='false'
288 B_TESTING_2='false'
289 B_UPLOAD_DEBUG_DATA='false'
290 B_USB_NETWORKING='false'
291 # set to true here for debug logging from script start
292 B_USE_LOGGING='false'
293 B_UUID_SET='false'
294 B_XORG_LOG='false'
295
296 ### Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]]
297 B_ASOUND_DEVICE_FILE='false'
298 B_ASOUND_VERSION_FILE='false'
299 B_BASH_ARRAY='false'
300 B_CPUINFO_FILE='false'
301 B_LSB_FILE='false'
302 B_MEMINFO_FILE='false'
303 B_MODULES_FILE='false' #
304 B_MOUNTS_FILE='false'
305 B_PARTITIONS_FILE='false' #
306 B_PROC_DIR='false'
307 B_SCSI_FILE='false'
308
309 ### File's used when present
310 FILE_ASOUND_DEVICE='/proc/asound/cards'
311 FILE_ASOUND_MODULES='/proc/asound/modules' # not used but maybe for -A?
312 FILE_ASOUND_VERSION='/proc/asound/version'
313 FILE_CPUINFO='/proc/cpuinfo'
314 FILE_LSB_RELEASE='/etc/lsb-release'
315 FILE_MEMINFO='/proc/meminfo'
316 FILE_MODULES='/proc/modules'
317 FILE_MOUNTS='/proc/mounts'
318 FILE_PARTITIONS='/proc/partitions'
319 FILE_SCSI='/proc/scsi/scsi'
320 FILE_XORG_LOG='/var/log/Xorg.0.log' # if not found, search and replace with actual location
321
322 ## app tested for and present, to avoid repeat tests
323 B_FILE_TESTED='false'
324 B_HDDTEMP_TESTED='false'
325 B_MODINFO_TESTED='false'
326 B_SUDO_TESTED='false'
327 FILE_PATH=''
328 HDDTEMP_PATH=''
329 MODINFO_PATH=''
330 SUDO_PATH=''
331
332 ### Variable initializations: constants
333 DCOPOBJ="default"
334 DEBUG=0 # Set debug levels from 1-10 (8-10 trigger logging levels)
335 # Debug Buffer Index, index into a debug buffer storing debug messages until inxi is 'all up'
336 DEBUG_BUFFER_INDEX=0
337 ## note: the debugger rerouting to /dev/null has been moved to the end of the get_parameters function
338 ## so -@[number] debug levels can be set if there is a failure, otherwise you can't even see the errors
339
340 # Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Use following variables in config 
341 # files to change defaults for each type, or global
342 # Same as runtime parameter.
343 DEFAULT_COLOR_SCHEME=2
344 # Always leave these blank, these are only going to be set in inxi.conf files, that makes testing
345 # for user changes easier after sourcing the files
346 GLOBAL_COLOR_SCHEME=''
347 IRC_COLOR_SCHEME=''
348 IRC_CONS_COLOR_SCHEME=''
349 IRC_X_TERM_COLOR_SCHEME=''
350 CONSOLE_COLOR_SCHEME=''
351 VIRT_TERM_COLOR_SCHEME=''
352
353 # Default indentation level
354 INDENT=10
355
356 # logging eval variables, start and end function: Insert to LOGFS LOGFE when debug level >= 8
357 LOGFS_STRING='log_function_data fs $FUNCNAME "$( echo $@ )"'
358 LOGFE_STRING='log_function_data fe $FUNCNAME'
359 LOGFS=''
360 LOGFE=''
361 # uncomment for debugging from script start
362 # LOGFS=$LOGFS_STRING
363 # LOGFE=$LOGFE_STRING
364
365 # default to false, no konversation found, 1 is native konvi (qt3/KDE3) script mode, 2 is /cmd inxi start,
366 ##      3 is Konversation > 1.2 (qt4/KDE4) 
367 KONVI=0
368 # NO_CPU_COUNT=0        # Wether or not the string "dual" or similar is found in cpuinfo output. If so, avoid dups.
369 # This is a variable that controls how many parameters inxi will parse in a /proc/<pid>/cmdline file before stopping.
370 PARAMETER_LIMIT=30
371 SCHEME=0 # set default scheme - do not change this, it's set dynamically
372 # this is set in user prefs file, to override dynamic temp1/temp2 determination of sensors output in case
373 # cpu runs colder than mobo
374 SENSORS_CPU_NO=''
375 # SHOW_IRC=1 to avoid showing the irc client version number, or SHOW_IRC=0 to disable client information completely.
376 SHOW_IRC=2
377 # Verbosity level defaults to 0, this can also be set with -v0, -v2, -v3, etc as a parameter.
378 VERBOSITY_LEVEL=0
379 # Supported number of verbosity levels, including 0
380 VERBOSITY_LEVELS=7
381
382 # Clear nullglob, because it creates unpredictable situations with IFS=$'\n' ARR=($VAR) IFS="$ORIGINAL_IFS"
383 # type constructs. Stuff like [rev a1] is now seen as a glob expansion pattern, and fails, and
384 # therefore results in nothing.
385 shopt -u nullglob
386 ## info on bash built in: $IFS - http://tldp.org/LDP/abs/html/internalvariables.html
387 # Backup the current Internal Field Separator
388 ORIGINAL_IFS="$IFS"
389
390 # These two determine separators in single line output, to force irc clients not to break off sections
391 SEP1='~'
392 SEP2=' '
393 # these will assign a separator to non irc states. Important! Using ':' can trigger stupid emoticon
394 # behaviors in output on IRC, so do not use those.
395 SEP3_IRC=''
396 SEP3_CONSOLE=':'
397 SEP3='' # do not set, will be set dynamically
398
399 ### Script names/paths - must be non root writable
400 SCRIPT_DATA_DIR="$HOME/.inxi"
401 ALTERNATE_FTP='' # for data uploads
402 LOG_FILE="$SCRIPT_DATA_DIR/inxi.log"
403 LOG_FILE_1="$SCRIPT_DATA_DIR/inxi.1.log"
404 LOG_FILE_2="$SCRIPT_DATA_DIR/inxi.2.log"
405 SCRIPT_NAME="inxi"
406 SCRIPT_PATCH_NUMBER=''
407 SCRIPT_PATH=""                  #filled-in in Main
408 SCRIPT_VERSION_NUMBER=""        #filled-in in Main
409 SCRIPT_DOWNLOAD='http://inxi.googlecode.com/svn/trunk/'
410 SCRIPT_DOWNLOAD_BRANCH_1='http://inxi.googlecode.com/svn/branches/one/'
411 SCRIPT_DOWNLOAD_BRANCH_2='http://inxi.googlecode.com/svn/branches/two/'
412 SCRIPT_DOWNLOAD_BRANCH_3='http://inxi.googlecode.com/svn/branches/three/'
413 SCRIPT_DOWNLOAD_BRANCH_4='http://inxi.googlecode.com/svn/branches/four/'
414 SCRIPT_DOWNLOAD_DEV='http://smxi.org/test/'
415 KONVI_CFG="konversation/scripts/$SCRIPT_NAME.conf" # relative path to $(kde-config --path data)
416
417 ### Script Localization
418 # Make sure every program speaks English.
419 LC_ALL="C"
420 export LC_ALL
421
422 ### Output Colors
423 # A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below.
424 unset EMPTY
425 #             DGREY   BLACK   RED     DRED    GREEN   DGREEN  YELLOW  DYELLOW
426 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"
427 IRC_COLORS="  \x0314  \x0301  \x0304  \x0305  \x0309  \x0303  \x0308  \x0307"
428 #                          BLUE    DBLUE   MAGENTA DMAGENTA CYAN   DCYAN   WHITE   GREY    NORMAL
429 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"
430 IRC_COLORS=" $IRC_COLORS    \x0312 \x0302  \x0313  \x0306  \x0311  \x0310  \x0300  \x0315  \x03"
431
432 #ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS)
433 A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL )
434
435 # See above for notes on EMPTY
436 ## note: group 1: 0, 1 are null/normal
437 ## Following: group 2: generic, light/dark or dark/light; group 3: dark on light; group 4 light on dark; 
438 # this is the count of the first two groups, starting at zero
439 SAFE_COLOR_COUNT=12
440 A_COLOR_SCHEMES=( 
441 EMPTY,EMPTY,EMPTY 
442 NORMAL,NORMAL,NORMAL 
443
444 BLUE,NORMAL,NORMAL
445 BLUE,RED,NORMAL 
446 CYAN,BLUE,NORMAL 
447 DCYAN,NORMAL,NORMAL
448 DCYAN,BLUE,NORMAL 
449 DGREEN,NORMAL,NORMAL 
450 DYELLOW,NORMAL,NORMAL 
451 GREEN,DGREEN,NORMAL 
452 GREEN,NORMAL,NORMAL 
453 MAGENTA,NORMAL,NORMAL
454 RED,NORMAL,NORMAL
455
456 BLACK,DGREY,NORMAL
457 DBLUE,DGREY,NORMAL 
458 DBLUE,DMAGENTA,NORMAL
459 DBLUE,DRED,NORMAL 
460 DBLUE,BLACK,NORMAL
461 DGREEN,DYELLOW,NORMAL 
462 DYELLOW,BLACK,NORMAL
463 DMAGENTA,BLACK,NORMAL
464 DCYAN,DBLUE,NORMAL
465
466 WHITE,GREY,NORMAL
467 GREY,WHITE,NORMAL
468 CYAN,GREY,NORMAL 
469 GREEN,WHITE,NORMAL 
470 GREEN,YELLOW,NORMAL 
471 YELLOW,WHITE,NORMAL 
472 MAGENTA,CYAN,NORMAL 
473 MAGENTA,YELLOW,NORMAL
474 RED,CYAN,NORMAL
475 RED,WHITE,NORMAL 
476 BLUE,WHITE,NORMAL
477 )
478
479 ## Actual color variables
480 C1=''
481 C2=''
482 CN=''
483
484 ### Distro Data
485 # In cases of derived distros where the version file of the base distro can also be found under /etc,
486 # the derived distro's version file should go first. (Such as with Sabayon / Gentoo)
487 DISTROS_DERIVED="antix-version aptosid-version kanotix-version knoppix-version mandrake-release pardus-release sabayon-release siduction-version sidux-version turbolinux-release zenwalk-version"
488 # debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu.
489 DISTROS_EXCLUDE_LIST="debian_version ubuntu_version"
490 DISTROS_PRIMARY="gentoo-release redhat-release slackware-version SuSE-release"
491 DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release"
492 ## Distros with known problems
493 # DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output
494 # Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially
495
496 ### Bans Data
497 # Note that \<ltd\> bans only words, not parts of strings; in \<corp\> you can't use punctuation characters like . or ,
498 # we're saving about 10+% of the total script exec time by hand building the ban lists here, using hard quotes.
499 BAN_LIST_NORMAL='computing|computer|corporation|communications|electronics|electrical|electric|gmbh|group|industrial|international|revision|software|technologies|technology|ltd\.|\<ltd\>|inc\.|\<inc\>|intl\.|co\.|\<co\>|corp\.|\<corp\>|\(tm\)|\(r\)|®|\(rev ..\)'
500 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]'
501
502 SENSORS_GPU_SEARCH='intel|radeon|nouveau'
503
504 ### USB networking search string data, because some brands can have other products than
505 ### wifi/nic cards, they need further identifiers, with wildcards.
506 ### putting the most common and likely first, then the less common, then some specifics
507 USB_NETWORK_SEARCH="Wi-Fi.*Adapter|Wireless.*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"
508 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" 
509 # then a few known hard to ID ones added 
510 # belkin=050d; d-link=07d1; netgear=0846; ralink=148f; realtek=0bda; 
511 USB_NETWORK_SEARCH="$USB_NETWORK_SEARCH|050d:935b|0bda:8189|0bda:8197"
512
513 # WARNING: In the main part below (search for 'KONVI')
514 # there's a check for Konversation-specific config files.
515 # Any one of these can override the above if inxi is run
516 # from Konversation!
517
518 ########################################################################
519 #### MAIN: Where it all begins
520 ########################################################################
521 main()
522 {
523         eval $LOGFS
524         
525         local color_scheme=''
526         
527         # This function just initializes variables
528         initialize_script_data
529
530         # Check for dependencies BEFORE running ANYTHING else except above functions
531         # Not all distro's have these depends installed by default. Don't want to run
532         # this if the user is requesting to see this information in the first place
533         if [[ $1 != '--recommends' ]];then
534                 check_script_depends
535                 check_script_suggested_apps
536         fi
537
538         ### Only continue if depends ok
539         SCRIPT_PATH=$( dirname $0 )
540         SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' )
541         SCRIPT_PATCH_NUMBER=$( grep -im 1 'Patch Number:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $4}' )
542         
543         ### Source global config overrides
544         if [[ -s /etc/$SCRIPT_NAME.conf ]];then
545                 source /etc/$SCRIPT_NAME.conf
546         fi
547         # Source user config variables override /etc/inxi.conf variables
548         if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then
549                 source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf
550         fi
551
552         ## this needs to run before the KONVI stuff is set below
553         ## Konversation 1.2 apparently does not like the $PPID test in get_start_client
554         ## So far there is no known way to detect if qt4_konvi is the parent process
555         ## this method will infer qt4_konvi as parent
556         get_start_client
557
558         # note: this only works if it's run from inside konversation as a script builtin or something
559         # only do this if inxi has been started as a konversation script, otherwise bypass this 
560 #       KONVI=3 ## for testing puroses
561         if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then
562                 if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3))    
563                         DCPORT="$1"
564                         DCSERVER="$2"
565                         DCTARGET="$3"
566                         shift 3
567                 elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4))
568                         DCSERVER="$1" ##dbus testing
569                         DCTARGET="$2" ##dbus testing
570                         shift 2
571                 fi
572
573                 # The section below is on request of Argonel from the Konversation developer team:
574                 # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf
575                 IFS=":"
576                 for kde_config in $( kde-config --path data )
577                 do
578                         if [[ -r ${kde_config}${KONVI_CFG} ]];then
579                                 source "${kde_config}${KONVI_CFG}"
580                                 break
581                         fi
582                 done
583                 IFS="$ORIGINAL_IFS"
584         fi
585
586         ## leave this for debugging dcop stuff if we get that working
587         #       print_screen_output "DCPORT: $DCPORT"
588         #       print_screen_output "DCSERVER: $DCSERVER"
589         #       print_screen_output "DCTARGET: $DCTARGET"
590         
591         # first init function must be set first for colors etc. Remember, no debugger
592         # stuff works on this function unless you set the debugging flag manually.
593         # Debugging flag -@ [number] will not work until get_parameters runs.
594         
595         # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter.
596         # must be here to allow debugger and other flags to be set.
597         get_parameters "$@"
598
599         # If no colorscheme was set in the parameter handling routine, then set the default scheme
600         if [[ $B_COLOR_SCHEME_SET != 'true' ]];then
601                 # This let's user pick their color scheme. For IRC, only shows the color schemes, no interactive
602                 # The override value only will be placed in user config files. /etc/inxi.conf can also override
603                 if [[ $B_RUN_COLOR_SELECTOR == 'true' ]];then 
604                         select_default_color_scheme
605                 else
606                         # set the default, then override as required
607                         color_scheme=$DEFAULT_COLOR_SCHEME
608                         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
609                                 color_scheme=$GLOBAL_COLOR_SCHEME
610                         else
611                                 if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
612                                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
613                                                 color_scheme=$CONSOLE_COLOR_SCHEME
614                                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
615                                                 color_scheme=$VIRT_TERM_COLOR_SCHEME
616                                         fi
617                                 else
618                                         if [[ -n $IRC_X_TERM_COLOR_SCHEME && $B_CONSOLE_IRC == 'true' && -n $DISPLAY ]];then
619                                                 color_scheme=$IRC_X_TERM_COLOR_SCHEME
620                                         elif [[ -n $IRC_CONS_COLOR_SCHEME && -z $DISPLAY ]];then
621                                                 color_scheme=$IRC_CONS_COLOR_SCHEME
622                                         elif [[ -n $IRC_COLOR_SCHEME ]];then
623                                                 color_scheme=$IRC_COLOR_SCHEME
624                                         fi
625                                 fi
626                         fi
627                         set_color_scheme $color_scheme
628                 fi
629         fi
630         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
631                 LINE_MAX=$LINE_MAX_CONSOLE
632                 SEP3=$SEP3_CONSOLE
633         else
634                 # too hard to read if no colors, so force that for users on irc
635                 if [[ $SCHEME == 0 ]];then
636                         SEP3=$SEP3_CONSOLE
637                 else
638                         SEP3=$SEP3_IRC
639                 fi
640                 LINE_MAX=$LINE_MAX_IRC
641         fi
642
643         # all the pre-start stuff is in place now
644         B_SCRIPT_UP='true'
645         script_debugger "Debugger: $SCRIPT_NAME is up and running..."
646         
647         # then create the output
648         print_it_out
649
650         ## last steps
651         if [[ $B_RUNNING_IN_SHELL == 'true' && $SCHEME -gt 0 ]];then
652                 echo -n "\e[0m"
653         fi
654         eval $LOGFE
655         # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code
656         # from the last command is taken..
657         exit 0
658 }
659
660 #### -------------------------------------------------------------------
661 #### basic tests: set script data, booleans, PATH
662 #### -------------------------------------------------------------------
663
664 # Set PATH data so we can access all programs as user. Set BAN lists.
665 # initialize some boleans, these directories are used throughout the script
666 # some apps are used for extended functions any directory used, should be
667 # checked here first.
668 # No args taken.
669 initialize_script_data()
670 {
671         eval $LOGFS
672         
673         # now set the script BOOLEANS for files required to run features
674         if [[ -d "/proc/" ]];then
675                 B_PROC_DIR='true'
676         else
677                 error_handler 6
678         fi
679         
680         initialize_script_paths
681         
682         # found a case of battery existing but having nothing in it on desktop mobo
683         # not all laptops show the first, 
684         if [[ -n $( ls /proc/acpi/battery 2>/dev/null ) ]];then
685                 B_PORTABLE='true'
686         fi
687         if [[ -e $FILE_CPUINFO ]]; then
688                 B_CPUINFO_FILE='true'
689         fi
690
691         if [[ -e $FILE_MEMINFO ]];then
692                 B_MEMINFO_FILE='true'
693         fi
694
695         if [[ -e $FILE_ASOUND_DEVICE ]];then
696                 B_ASOUND_DEVICE_FILE='true'
697         fi
698
699         if [[ -e $FILE_ASOUND_VERSION ]];then
700                 B_ASOUND_VERSION_FILE='true'
701         fi
702
703         if [[ -f $FILE_LSB_RELEASE ]];then
704                 B_LSB_FILE='true'
705         fi
706
707         if [[ -e $FILE_SCSI ]];then
708                 B_SCSI_FILE='true'
709         fi
710
711         if [[ -n $DISPLAY ]];then
712                 B_SHOW_X_DATA='true'
713                 B_RUNNING_IN_X='true'
714         fi
715
716         if [[ -e $FILE_MODULES ]];then
717                 B_MODULES_FILE='true'
718         fi
719
720         if [[ -e $FILE_MOUNTS ]];then
721                 B_MOUNTS_FILE='true'
722         fi
723
724         if [[ -e $FILE_PARTITIONS ]];then
725                 B_PARTITIONS_FILE='true'
726         fi
727         # default to the normal location, then search for it
728         if [[ -e $FILE_XORG_LOG ]];then
729                 B_XORG_LOG='true'
730         else
731                 # Detect location of the Xorg log file
732                 if [[ -n $( type -p xset ) ]]; then
733                         FILE_XORG_LOG=$( xset q 2>/dev/null | grep -i 'Log file' | gawk '{print $3}')
734                         if [[ -e $FILE_XORG_LOG ]];then
735                                 B_XORG_LOG='true'
736                         fi
737                 fi
738         fi
739         # gfx output will require this flag
740         if [[ $( whoami ) == 'root' ]];then
741                 B_ROOT='true'
742         fi
743         eval $LOGFE
744 }
745
746 initialize_script_paths()
747 {
748         local path='' added_path='' b_path_found='' sys_path=''
749         # Extra path variable to make execute failures less likely, merged below
750         local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
751
752         # Fallback paths put into $extra_paths; This might, among others, help on gentoo.
753         # Now, create a difference of $PATH and $extra_paths and add that to $PATH:
754         IFS=":"
755         for path in $extra_paths
756         do
757                 b_path_found='false'
758                 for sys_path in $PATH
759                 do
760                         if [[ $path == $sys_path ]];then
761                                 b_path_found='true'
762                         fi
763                 done
764                 if [[ $b_path_found == 'false' ]];then
765                         added_path="$added_path:$path"
766                 fi
767         done
768
769         IFS="$ORIGINAL_IFS"
770         PATH="${PATH}${added_path}"
771         ##echo "PATH='$PATH'"
772         ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""'
773 }
774
775 # No args taken.
776 check_script_suggested_apps()
777 {
778         eval $LOGFS
779         local bash_array_test=( "one" "two" )
780
781         # check for array ability of bash, this is only good for the warning at this time
782         # the boolean could be used later
783         # bash version 2.05b is used in DSL
784         # bash version 3.0 is used in Puppy Linux; it has a known array bug <reference to be placed here>
785         # versions older than 3.1 don't handle arrays
786         # distro's using below 2.05b are unknown, released in 2002
787         if [[ ${bash_array_test[1]} -eq "two" ]];then
788                 B_BASH_ARRAY='true'
789         else
790                 script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output"
791         fi
792         # now setting qdbus/dcop for first run, some systems can have both by the way
793         if [[ -n $( type -p qdbus ) ]];then
794                 B_QDBUS='true'
795         fi
796         if [[ -n $( type -p dcop ) ]];then
797                 B_DCOP='true'
798         fi
799         eval $LOGFE
800 }
801
802 # Determine if any of the absolutely necessary tools are absent
803 # No args taken.
804 check_script_depends()
805 {
806         eval $LOGFS
807         local app_name='' app_path=''
808         # bc removed from deps for now
809         local depends="df free gawk grep lspci ps readlink tr uname uptime wc"
810         # no need to add xprop because it will just give N/A if not there, but if we expand use of xprop,
811         # should add that here as a test, then use the B_SHOW_X_DATA flag to trigger the tests in de function
812         local x_apps="xrandr xdpyinfo glxinfo" 
813
814         if [[ $B_RUNNING_IN_X == 'true' ]];then
815                 for app_name in $x_apps
816                 do
817                         app_path=$( type -p $app_name )
818                         if [[ -z $app_path ]];then
819                                 script_debugger "Resuming in non X mode: $app_name not found. For package install advice run: $SCRIPT_NAME --recommends"
820                                 B_SHOW_X_DATA='false'
821                                 break
822                         fi
823                 done
824         fi
825
826         app_name=''
827
828         for app_name in $depends
829         do
830                 app_path=$( type -p $app_name )
831                 if [[ -z $app_path ]];then
832                         error_handler 5 "$app_name"
833                 fi
834         done
835         eval $LOGFE
836 }
837
838 ## note: this is now running inside each gawk sequence directly to avoid exiting gawk
839 ## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array
840 ## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods
841 # Enforce boilerplate and buzzword filters
842 # args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize
843 sanitize_characters()
844 {
845         eval $LOGFS
846         # Cannot use strong quotes to unquote a string with pipes in it!
847         # bash will interpret the |'s as usual and try to run a subshell!
848         # Using weak quotes instead, or use '"..."'
849         echo "$2" | gawk "
850         BEGIN {
851                 IGNORECASE=1
852         }
853         {
854                 gsub(/${!1}/,\"\")
855                 gsub(/ [ ]+/,\" \")    ## ([ ]+) with (space)
856                 gsub(/^ +| +$/,\"\")   ## (pipe char) with (nothing)
857                 print                  ## prints (returns) cleaned input
858         }"
859         eval $LOGFE
860 }
861
862 # Set the colorscheme
863 # args: $1 = <scheme number>|<"none">
864 set_color_scheme()
865 {
866         eval $LOGFS
867         local i='' a_script_colors='' a_color_codes=''
868
869         if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then
870                 set -- 1
871         fi
872         # Set a global variable to allow checking for chosen scheme later
873         SCHEME="$1"
874         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
875                 a_color_codes=( $ANSI_COLORS )
876         else
877                 a_color_codes=( $IRC_COLORS )
878         fi
879         for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ ))
880         do
881                 eval "${A_COLORS_AVAILABLE[i]}=\"${a_color_codes[i]}\""
882         done
883         IFS=","
884         a_script_colors=( ${A_COLOR_SCHEMES[$1]} )
885         IFS="$ORIGINAL_IFS"
886         # then assign the colors globally
887         C1="${!a_script_colors[0]}"
888         C2="${!a_script_colors[1]}"
889         CN="${!a_script_colors[2]}"
890         # ((COLOR_SCHEME++)) ## note: why is this? ##
891         eval $LOGFE
892 }
893
894 select_default_color_scheme()
895 {
896         eval $LOGFS
897         local spacer='  ' options='' user_selection='' config_variable=''
898         local config_file="$HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf"
899         local irc_clear="\e[0m" 
900         local irc_gui='Unset' irc_console='Unset' irc_x_term='Unset'
901         local console='Unset' virt_term='Unset' global='Unset' 
902         
903         if [[ -n $IRC_COLOR_SCHEME ]];then
904                 irc_gui="Set: $IRC_COLOR_SCHEME"
905         fi
906         if [[ -n $IRC_CONS_COLOR_SCHEME ]];then
907                 irc_console="Set: $IRC_CONS_COLOR_SCHEME"
908         fi
909         if [[ -n $IRC_X_TERM_COLOR_SCHEME ]];then
910                 irc_x_term="Set: $IRC_X_TERM_COLOR_SCHEME"
911         fi
912         if [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
913                 virt_term="Set: $VIRT_TERM_COLOR_SCHEME"
914         fi
915         if [[ -n $CONSOLE_COLOR_SCHEME ]];then
916                 console="Set: $CONSOLE_COLOR_SCHEME"
917         fi
918         if [[ -n $GLOBAL_COLOR_SCHEME ]];then
919                 global="Set: $GLOBAL_COLOR_SCHEME"
920         fi
921         
922         # don't want these printing in irc since they show literally
923         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
924                 irc_clear=''
925         fi
926         # first make output neutral so it's just plain default for console client
927         set_color_scheme "0"
928         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
929                 print_screen_output "Welcome to $SCRIPT_NAME! Please select the default $COLOR_SELECTION color scheme."
930                 # print_screen_output "You will see this message only one time per user account, unless you set preferences in: /etc/$SCRIPT_NAME.conf"
931                 print_screen_output " "
932         fi
933         print_screen_output "Because there is no way to know your $COLOR_SELECTION foreground/background colors, you can"
934         print_screen_output "set your color preferences from color scheme option list below. 0 is no colors, 1 neutral."
935         print_screen_output "After these, there are 3 sets: 1-dark or light backgrounds; 2-light backgrounds; 3-dark backgrounds."
936         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
937                 print_screen_output "Please note that this will set the $COLOR_SELECTION preferences only for user: $(whoami)"
938         fi
939         print_screen_output "------------------------------------------------------------------------------"
940         for (( i=0; i < ${#A_COLOR_SCHEMES[@]}; i++ ))
941         do
942                 if [[ $i -gt 9 ]];then
943                         spacer=' '
944                 fi
945                 # only offer the safe universal defaults
946                 case $COLOR_SELECTION in
947                         global|irc|irc-console|irc-virtual-terminal)
948                                 if [[ $i -gt $SAFE_COLOR_COUNT ]];then
949                                         break
950                                 fi
951                                 ;;
952                 esac
953                 set_color_scheme $i
954                 print_screen_output "$irc_clear $i)$spacer${C1}Card:${C2} nVidia G86 [GeForce 8400 GS] ${C1}X.Org${C2} 1.7.7"
955         done
956         set_color_scheme 0
957         
958         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
959                 echo -n "\e[0m"
960                 print_screen_output "$irc_clear $i)${spacer}Remove all color settings. Restore $SCRIPT_NAME default."
961                 print_screen_output "$irc_clear $(($i+1)))${spacer}Continue, no changes or config file setting."
962                 print_screen_output "$irc_clear $(($i+2)))${spacer}Exit, use another terminal, or set manually."
963                 print_screen_output "------------------------------------------------------------------------------"
964                 print_screen_output "Simply type the number for the color scheme that looks best to your eyes for your $COLOR_SELECTION settings"
965                 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:"
966                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
967                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
968                 print_screen_output "Your selection(s) will be stored here: $config_file"
969                 print_screen_output "Global overrides all individual color schemes. Individual schemes remove the global setting."
970                 print_screen_output "------------------------------------------------------------------------------"
971                 read user_selection
972                 if [[ -n $( grep -Es '^([0-9]+)$' <<< "$user_selection" ) && $user_selection -lt $i ]];then
973                         case $COLOR_SELECTION in
974                                 irc)
975                                         config_variable='IRC_COLOR_SCHEME'
976                                         ;;
977                                 irc-console)
978                                         config_variable='IRC_CONS_COLOR_SCHEME'
979                                         ;;
980                                 irc-virtual-terminal)
981                                         config_variable='IRC_X_TERM_COLOR_SCHEME'
982                                         ;;
983                                 console)
984                                         config_variable='CONSOLE_COLOR_SCHEME'
985                                         ;;
986                                 virtual-terminal)
987                                         config_variable='VIRT_TERM_COLOR_SCHEME'
988                                         ;;
989                                 global)
990                                         config_variable='GLOBAL_COLOR_SCHEME'
991                                         ;;
992                         esac
993                         set_color_scheme $user_selection
994                         # make file/directory first if missing
995                         if [[ ! -f $config_file ]];then
996                                 if [[ ! -d $HOME/.$SCRIPT_NAME ]];then
997                                         mkdir $HOME/.$SCRIPT_NAME
998                                 fi
999                                 touch $config_file
1000                         fi
1001                         if [[ -z $( grep -s "$config_variable=" $config_file ) ]];then
1002                                 print_screen_output "Creating and updating config file for $COLOR_SELECTION color scheme now..."
1003                                 echo "$config_variable=$user_selection" >> $config_file
1004                         else
1005                                 print_screen_output "Updating config file for $COLOR_SELECTION color scheme now..."
1006                                 sed -i "s/$config_variable=.*/$config_variable=$user_selection/" $config_file
1007                         fi
1008                         # file exists now so we can go on to cleanup
1009                         case $COLOR_SELECTION in
1010                                 irc|irc-console|irc-virtual-terminal|console|virtual-terminal)
1011                                         sed -i '/GLOBAL_COLOR_SCHEME=/d' $config_file
1012                                         ;;
1013                                 global)
1014                                         sed -i -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' -e '/IRC_COLOR_SCHEME=/d' \
1015                                         -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1016                                         ;;
1017                         esac
1018                 elif [[ $user_selection == $i ]];then
1019                         print_screen_output "Removing all color settings from config file now..."
1020                         sed -i -e '/VIRT_TERM_COLOR_SCHEME=/d' -e '/GLOBAL_COLOR_SCHEME=/d' -e '/CONSOLE_COLOR_SCHEME=/d' \
1021                         -e '/IRC_COLOR_SCHEME=/d' -e '/IRC_CONS_COLOR_SCHEME=/d' -e '/IRC_X_TERM_COLOR_SCHEME=/d' $config_file
1022                         set_color_scheme $DEFAULT_COLOR_SCHEME
1023                 elif [[ $user_selection == $(( $i+1 )) ]];then
1024                         print_screen_output "Ok, continuing $SCRIPT_NAME unchanged. You can set the colors anytime by starting with: -c 95 to 99"
1025                         if [[ -n $CONSOLE_COLOR_SCHEME && -z $DISPLAY ]];then
1026                                 set_color_scheme $CONSOLE_COLOR_SCHEME
1027                         elif [[ -n $VIRT_TERM_COLOR_SCHEME ]];then
1028                                 set_color_scheme $VIRT_TERM_COLOR_SCHEME
1029                         else
1030                                 set_color_scheme $DEFAULT_COLOR_SCHEME
1031                         fi
1032                 elif [[ $user_selection == $(( $i+2 )) ]];then
1033                         set_color_scheme $DEFAULT_COLOR_SCHEME
1034                         print_screen_output "Ok, exiting $SCRIPT_NAME now. You can set the colors later."
1035                         exit 0
1036                 else
1037                         print_screen_output "Error - Invalid Selection. You entered this: $user_selection"
1038                         print_screen_output " "
1039                         select_default_color_scheme
1040                 fi
1041         else
1042                 print_screen_output "------------------------------------------------------------------------------"
1043                 print_screen_output "After finding the scheme number you like, simply run this again in a terminal to set the configuration"
1044                 print_screen_output "data file for your irc client. You can set color schemes for the following: start inxi with -c plus:"
1045                 print_screen_output "94 (console, no X - $console); 95 (terminal, X - $virt_term); 96 (irc, gui, X - $irc_gui);"
1046                 print_screen_output "97 (irc, X, in terminal - $irc_x_term); 98 (irc, no X - $irc_console); 99 (global - $global)"
1047                 exit 0
1048         fi
1049
1050         eval $LOGFE
1051 }
1052
1053 ########################################################################
1054 #### UTILITY FUNCTIONS
1055 ########################################################################
1056
1057 #### -------------------------------------------------------------------
1058 #### error handler, debugger, script updater
1059 #### -------------------------------------------------------------------
1060
1061 # Error handling
1062 # args: $1 - error number; $2 - optional, extra information
1063 error_handler()
1064 {
1065         eval $LOGFS
1066         local error_message=''
1067
1068         # assemble the error message
1069         case $1 in
1070                 2)      error_message="large flood danger, debug buffer full!"
1071                         ;;
1072                 3)      error_message="unsupported color scheme number: $2"
1073                         ;;
1074                 4)      error_message="unsupported verbosity level: $2"
1075                         ;;
1076                 5)      error_message="dependency not met: $2 not found in path.\nFor distribution installation package names and missing apps information, run: $SCRIPT_NAME --recommends"
1077                         ;;
1078                 6)      error_message="/proc not found! Quitting..."
1079                         ;;
1080                 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"
1081                         ;;
1082                 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"
1083                         ;;
1084                 9)      error_message="unsupported debugging level: $2"
1085                         ;;
1086                 10)
1087                         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/"
1088                         ;;
1089                 11)
1090                         error_message="unsupported testing option argument: -! $2"
1091                         ;;
1092                 12)
1093                         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."
1094                         ;;
1095                 13)
1096                         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"
1097                         ;;
1098                 14)
1099                         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"
1100                         ;;
1101                 15)
1102                         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"
1103                         ;;
1104                 16)
1105                         error_message="$SCRIPT_NAME downloaded but the file data is corrupted. Purged data and using current version."
1106                         ;;
1107                 20)
1108                         error_message="The option you selected has been deprecated. $2\nSee the -h (help) menu for currently supported options."
1109                         ;;
1110                 *)      error_message="error unknown: $@"
1111                         set -- 99
1112                         ;;
1113         esac
1114         # then print it and exit
1115         print_screen_output "Error $1: $error_message"
1116         eval $LOGFE
1117         exit $1
1118 }
1119
1120 # prior to script up set, pack the data into an array
1121 # then we'll print it out later.
1122 # args: $1 - $@ debugging string text
1123 script_debugger()
1124 {
1125         eval $LOGFS
1126         if [[ $B_SCRIPT_UP == 'true' ]];then
1127                 # only return if debugger is off and no pre start up errors have occured
1128                 if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then
1129                         return 0
1130                 # print out the stored debugging information if errors occured
1131                 elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then
1132                         for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ ))
1133                         do
1134                                 print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}"
1135                         done
1136                         DEBUG_BUFFER_INDEX=0
1137                 fi
1138                 # or print out normal debugger messages if debugger is on
1139                 if [[ $DEBUG -gt 0 ]];then
1140                         print_screen_output "$1"
1141                 fi
1142         else
1143                 if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then
1144                         error_handler 2
1145                 # this case stores the data for later printout, will print out only
1146                 # at B_SCRIPT_UP == 'true' if array index > 0
1147                 else
1148                         A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1"
1149                         # increment count for next pre script up debugging error
1150                         (( DEBUG_BUFFER_INDEX++ ))
1151                 fi
1152         fi
1153         eval $LOGFE
1154 }
1155
1156 # NOTE: no logging available until get_parameters is run, since that's what sets logging
1157 # in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables.
1158 # $1 alone: logs data; $2 with or without $3 logs func start/end.
1159 # $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]]
1160 log_function_data()
1161 {
1162         if [ "$B_USE_LOGGING" == 'true' ];then
1163                 local logged_data='' spacer='   ' line='----------------------------------------'
1164                 case $1 in
1165                         fs)
1166                                 logged_data="Function: $2 - Primary: Start"
1167                                 if [ -n "$3" ];then
1168                                         logged_data="$logged_data\n${spacer}Args: $3"
1169                                 fi
1170                                 spacer=''
1171                                 ;;
1172                         fe)
1173                                 logged_data="Function: $2 - Primary: End"
1174                                 spacer=''
1175                                 ;;
1176                         cat)
1177                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1178                                         logged_data="\n$line\nFull file data: cat $2\n\n$( cat $2 )\n$line\n"
1179                                         spacer=''
1180                                 fi
1181                                 ;;
1182                         raw)
1183                                 if [[ $B_LOG_FULL_DATA == 'true' ]];then
1184                                         logged_data="\n$line\nRaw system data:\n\n$2\n$line\n"
1185                                         spacer=''
1186                                 fi
1187                                 ;;
1188                         *)
1189                                 logged_data="$1"
1190                                 ;;
1191                 esac
1192                 # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2).
1193                 # This pattern doesn't work for irc colors, if we need that someone can figure it out
1194                 if [[ -n $logged_data ]];then
1195                         if [[ $B_LOG_COLORS != 'true' ]];then
1196                                 echo -e "${spacer}$logged_data" | sed -r 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE
1197                         else
1198                                 echo -e "${spacer}$logged_data" >> $LOG_FILE
1199                         fi
1200                 fi
1201         fi
1202 }
1203
1204 # called in the initial -@ 10 script args setting so we can get logging as soon as possible
1205 # will have max 3 files, inxi.log, inxi.1.log, inxi.2.log
1206 create_rotate_logfiles()
1207 {
1208         if [[ ! -d $SCRIPT_DATA_DIR ]];then
1209                 mkdir $SCRIPT_DATA_DIR
1210         fi
1211         # do the rotation if logfile exists
1212         if [[ -f $LOG_FILE ]];then
1213                 # copy if present second to third
1214                 if [[ -f $LOG_FILE_1 ]];then
1215                         mv -f $LOG_FILE_1 $LOG_FILE_2
1216                 fi
1217                 # then copy initial to second
1218                 mv -f $LOG_FILE $LOG_FILE_1
1219         fi
1220         # now create the logfile
1221         touch $LOG_FILE
1222         # and echo the start data
1223         echo "=========================================================" >> $LOG_FILE
1224         echo "START $SCRIPT_NAME LOGGING:"                               >> $LOG_FILE
1225         echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )"              >> $LOG_FILE
1226         echo "=========================================================" >> $LOG_FILE
1227 }
1228
1229 # args: $1 - download url, not including file name; $2 - string to print out
1230 # note that $1 must end in / to properly construct the url path
1231 script_self_updater()
1232 {
1233         eval $LOGFS
1234         local wget_error=0 file_contents=''
1235         print_screen_output "Starting $SCRIPT_NAME self updater."
1236         print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER"
1237         print_screen_output "Current version patch number: $SCRIPT_PATCH_NUMBER"
1238         print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..."
1239
1240         file_contents="$( wget -q -O - $1$SCRIPT_NAME )" || wget_error=$?
1241         # then do the actual download
1242         if [[  $wget_error -eq 0 ]];then
1243                 # make sure the whole file got downloaded and is in the variable
1244                 if [[ -n $( grep '###\*\*EOF\*\*###' <<< "$file_contents" ) ]];then
1245                         echo "$file_contents" > $SCRIPT_PATH/$SCRIPT_NAME || error_handler 14 "$?"
1246                         chmod +x $SCRIPT_PATH/$SCRIPT_NAME || error_handler 15 "$?"
1247                         SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' )
1248                         SCRIPT_PATCH_NUMBER=$( grep -im 1 'Patch Number:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $4}' )
1249                         print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER"
1250                         print_screen_output "New $2 version patch number: $SCRIPT_PATCH_NUMBER"
1251                         print_screen_output "To run the new version, just start $SCRIPT_NAME again."
1252                         exit 0
1253                 else
1254                         error_handler 16
1255                 fi
1256         # now run the error handlers on any wget failure
1257         else
1258                 if [[ $2 == 'svn server' ]];then
1259                         error_handler 8 "$wget_error"
1260                 elif [[ $2 == 'alt server' ]];then
1261                         error_handler 10 "$1"
1262                 else
1263                         error_handler 12 "$1"
1264                 fi
1265         fi
1266         eval $LOGFS
1267 }
1268
1269 # args: $1 - debug data type: sys|xorg|disk
1270 debug_data_collector()
1271 {
1272         local xiin_app='' xiin_data_file='' xiin_download='' error='' b_run_xiin='false'
1273         local debug_data_dir="inxi-$(tr ' ' '-' <<< $HOSTNAME | tr '[A-Z]' '[a-z]' )-$1-$(date +%Y%m%d)" 
1274         local completed_gz_file='' xiin_file='xiin.py' ftp_upload='ftp.techpatterns.com/incoming'
1275         local Line='-------------------------'
1276         
1277         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
1278                 if [[ -n $ALTERNATE_FTP ]];then
1279                         ftp_upload=$ALTERNATE_FTP
1280                 fi
1281                 echo "Starting debugging data collection type: $1"
1282                 echo -n "Checking/creating required directories... "
1283                 if [[ ! -d $SCRIPT_DATA_DIR ]];then
1284                         mkdir $SCRIPT_DATA_DIR
1285                 fi
1286                 echo 'completed'
1287                 cd $SCRIPT_DATA_DIR
1288                 if [[ -d $debug_data_dir ]];then
1289                         echo 'Deleting previous xiin data directory...'
1290                         rm -rf $debug_data_dir
1291                 fi
1292                 mkdir $debug_data_dir
1293                 if [[ -f $debug_data_dir.tar.gz ]];then
1294                         echo 'Deleting previous tar.gz file...'
1295                         rm -f $debug_data_dir.tar.gz
1296                 fi
1297                 
1298                 echo 'Collecting system info: sensors, lsusb, lspci, lspci -v data, plus /proc data'
1299                 lsusb &> $debug_data_dir/lsusb.txt
1300                 lspci &> $debug_data_dir/lspci.txt
1301                 lspci -v &> $debug_data_dir/lspci-v.txt
1302                 ps aux &> $debug_data_dir/ps-aux.txt
1303                 sensors &> $debug_data_dir/sensors.txt
1304                 ls /usr/bin/gcc* &> $debug_data_dir/gcc-sys-versions.txt
1305                 gcc --version &> $debug_data_dir/gcc-version.txt
1306                 cat $FILE_LSB_RELEASE &> $debug_data_dir/lsb-release.txt
1307                 cat $FILE_ASOUND_DEVICE &> $debug_data_dir/proc-asound-device.txt
1308                 cat $FILE_ASOUND_VERSION &> $debug_data_dir/proc-asound-version.txt
1309                 cat $FILE_CPUINFO &> $debug_data_dir/proc-cpu-info.txt
1310                 cat $FILE_MEMINFO &> $debug_data_dir/proc-meminfo.txt
1311                 cat $FILE_MODULES &> $debug_data_dir/proc-modules.txt
1312                 cat /proc/net/arp &> $debug_data_dir/proc-net-arp.txt 
1313                 check_recommends &> $debug_data_dir/check-recommends.txt
1314                 # first download and verify xiin
1315                 if [[ $B_UPLOAD_DEBUG_DATA == 'true' || $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1316                         touch $debug_data_dir/xiin-error.txt
1317                         echo "Downloading required tree traverse tool $xiin_file..."
1318                         if [[ -f xiin && ! -f $xiin_file ]];then
1319                                 mv -f xiin $xiin_file
1320                         fi
1321                         # -Nc is creating really weird download anomolies, so using -O instead
1322                         xiin_download="$( wget -q -O - http://inxi.googlecode.com/svn/branches/xiin/$xiin_file )"
1323                         # if nothing got downloaded kick out error, otherwise we'll use an older version
1324                         if [[ $? -gt 0 && ! -f $xiin_file ]];then
1325                                 echo -e "ERROR: Failed to download required file: $xiin_file\nMaybe the remote site is down or your networking is broken?"
1326                                 echo "Continuing with incomplete data collection."
1327                                 echo "$xiin_file download failed and no existing $xiin_file" >> $debug_data_dir/xiin-error.txt
1328                         elif [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) || -f $xiin_file ]];then
1329                                 if [[ -n $( grep -s '# EOF' <<< "$xiin_download" ) ]];then
1330                                         echo "Updating $xiin_file from remote location"
1331                                         echo "$xiin_download" > $xiin_file
1332                                 else
1333                                         echo "Using local $xiin_file due to download failure"
1334                                 fi
1335                                 b_run_xiin='true'
1336                         else
1337                                 echo -e "ERROR: $xiin_file downloaded but the program file data is corrupted.\nContinuing with incomplete data collection."
1338                                 echo "$xiin_file downloaded but the program file data is corrupted." >> $debug_data_dir/xiin-error.txt
1339                         fi
1340                 fi
1341                 # note, only bash 4> supports ;;& for case, so using if/then here
1342                 if [[ $1 == 'disk' || $1 == 'sys' || $1 == 'all' ]];then
1343                         xiin_data_file=$SCRIPT_DATA_DIR/$debug_data_dir/xiin-sys.txt
1344                         echo 'Collecting networking data...'
1345                         ifconfig &> $debug_data_dir/ifconfig.txt
1346                         ip addr &> $debug_data_dir/ip-addr.txt
1347                         if [[ $b_run_xiin == 'true' ]];then
1348                                 echo $Line
1349                                 echo "Running $xiin_file tool now on /sys..."
1350                                 python ./$xiin_file -d /sys -f $xiin_data_file
1351                                 if [[ $? -ne 0 ]];then
1352                                         error=$?
1353                                         echo -e "ERROR: $xiin_file exited with error $error - removing data file.\nContinuing with incomplete data collection."
1354                                         echo "Continuing with incomplete data collection."
1355                                         rm -f $xiin_data_file
1356                                         echo "$xiin_file data generation failed with python error $error" >> $debug_data_dir/xiin-error.txt
1357                                 fi
1358                                 echo $Line
1359                         fi
1360                 fi
1361                 if [[ $1 == 'xorg' || $1 == 'all' ]];then
1362                         if [[ $B_RUNNING_IN_X != 'true' ]];then
1363                                 echo 'Warning: only some of the data collection can occur if you are not in X'
1364                                 touch $debug_data_dir/warning-user-not-in-x
1365                         fi
1366                         if [[ $B_ROOT == 'true' ]];then
1367                                 echo 'Warning: only some of the data collection can occur if you are running as Root user'
1368                                 touch $debug_data_dir/warning-root-user
1369                         fi
1370                         echo 'Collecting Xorg log and xorg.conf files'
1371                         if [[ -e $FILE_XORG_LOG ]];then
1372                                 cat $FILE_XORG_LOG &> $debug_data_dir/xorg-log-file.txt
1373                         else
1374                                 touch $debug_data_dir/no-xorg-log-file
1375                         fi
1376                         if [[ -e /etc/X11/xorg.conf ]];then
1377                                 cp /etc/X11/xorg.conf $debug_data_dir
1378                         else
1379                                 touch $debug_data_dir/no-xorg-conf-file
1380                         fi
1381                         if [[ -n $( ls /etc/X11/xorg.conf.d/ 2>/dev/null ) ]];then
1382                                 ls /etc/X11/xorg.conf.d &> $debug_data_dir/ls-etc-x11-xorg-conf-d.txt
1383                                 cp /etc/X11/xorg.conf.d $debug_data_dir
1384                         else
1385                                 touch $debug_data_dir/no-xorg-conf-d-files
1386                         fi
1387                         echo 'Collecting X, xprop, glxinfo, xrandr, xdpyinfo data...'
1388                         xprop -root &> $debug_data_dir/xprop_root.txt
1389                         glxinfo &> $debug_data_dir/glxinfo.txt
1390                         xdpyinfo &> $debug_data_dir/xdpyinfo.txt
1391                         xrandr &> $debug_data_dir/xrandr.txt
1392                         X -version &> $debug_data_dir/x-version.txt
1393                         Xorg -version &> $debug_data_dir/xorg-version.txt
1394                 fi
1395                 if [[ $1 == 'disk' || $1 == 'all' ]];then
1396                         echo 'Collecting dev, label, disk, uuid data, df...'
1397                         ls -l /dev &> $debug_data_dir/dev-data.txt
1398                         ls -l /dev/disk &> $debug_data_dir/dev-disk-data.txt
1399                         ls -l /dev/disk/by-id &> $debug_data_dir/dev-disk-id-data.txt
1400                         ls -l /dev/disk/by-label &> $debug_data_dir/dev-disk-label-data.txt
1401                         ls -l /dev/disk/by-uuid &> $debug_data_dir/dev-disk-uuid-data.txt
1402                         ls -l /dev/disk/by-path &> $debug_data_dir/dev-disk-path-data.txt
1403                         readlink /dev/root &> $debug_data_dir/dev-root.txt
1404                         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-excludes.txt
1405                         swapon -s &> $debug_data_dir/swapon-s.txt
1406                         df -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 &> $debug_data_dir/df-excludes.txt
1407                         cat $FILE_PARTITIONS &> $debug_data_dir/proc-partitions.txt
1408                         cat $FILE_SCSI &> $debug_data_dir/proc-scsi.txt
1409                         cat $FILE_MOUNTS &> $debug_data_dir/proc-mounts.txt
1410                         cat /proc/sys/dev/cdrom/info &> $debug_data_dir/proc-cdrom-info.txt
1411                         ls /proc/ide/ &> $debug_data_dir/proc-ide.txt
1412                         cat /proc/ide/*/* &> $debug_data_dir/proc-ide-hdx-cat.txt
1413                         cat /etc/fstab &> $debug_data_dir/etc-fstab.txt
1414                         cat /etc/mtab &> $debug_data_dir/etc-mtab.txt
1415                 fi
1416                 echo 'Creating inxi output file now. This can take a few seconds...'
1417                 $SCRIPT_NAME -Fploudxx -c 0 -@ 8 > $debug_data_dir/inxi-Fploudxx.txt
1418                 cp $LOG_FILE $SCRIPT_DATA_DIR/$debug_data_dir
1419                 if [[ -f $debug_data_dir.tar.gz ]];then
1420                         echo "Found and removing previous tar.gz data file: $debug_data_dir.tar.gz"
1421                         rm -f $debug_data_dir.tar.gz
1422                 fi
1423                 echo 'Creating tar.gz compressed file of this material now. Contents:'
1424                 echo $Line
1425                 tar -cvzf $debug_data_dir.tar.gz $debug_data_dir
1426                 echo $Line
1427                 echo 'Cleaning up leftovers...'
1428                 rm -rf $debug_data_dir
1429                 echo 'Testing gzip file integrity...'
1430                 gzip -t $debug_data_dir.tar.gz
1431                 if [[ $? -gt 0 ]];then
1432                         echo 'Data in gz is corrupted, removing gzip file, try running data collector again.'
1433                         rm -f $debug_data_dir.tar.gz
1434                         echo "Data in gz is corrupted, removed gzip file" >> $debug_data_dir/gzip-error.txt
1435                 else
1436                         echo 'All done, you can find your data gzipped directory here:'
1437                         completed_gz_file=$SCRIPT_DATA_DIR/$debug_data_dir.tar.gz
1438                         echo $completed_gz_file
1439                         if [[ $B_UPLOAD_DEBUG_DATA == 'true' ]];then
1440                                 echo $Line
1441                                 if [[ $b_run_xiin == 'true' ]];then
1442                                         echo "Running automatic upload of data to remote server $ftp_upload now..."
1443                                         python ./$xiin_file --version
1444                                         python ./$xiin_file -u $completed_gz_file $ftp_upload
1445                                         if [[ $? -gt 0 ]];then
1446                                                 echo $Line
1447                                                 echo "Error: looks like the ftp upload failed. Error number: $?"
1448                                                 echo "The ftp upload failed. Error number: $?" >> $debug_data_dir/xiin-error.txt
1449                                         fi
1450                                 else
1451                                         echo 'Unable to run the automoatic ftp upload because of an error with the xiin download.'
1452                                         echo "Unable to run the automoatic ftp upload because of an error with the xiin download" >> $debug_data_dir/xiin-error.txt
1453                                 fi
1454                         else
1455                                 echo 'You can upload this here using most file managers: ftp.techpatterns.com/incoming'
1456                                 echo 'then let a maintainer know it is uploaded.'
1457                         fi
1458                 fi
1459         else
1460                 echo 'This feature only available in console or shell client! Exiting now.'
1461         fi
1462         exit 0
1463 }
1464
1465 check_recommends()
1466 {
1467         local Line='-----------------------------------------------------------------------------------------'
1468         local gawk_version='N/A' sed_version='N/A' sudo_version='N/A' python_version='N/A'
1469         
1470         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
1471                 print_screen_output "Sorry, you can't run this option in an IRC client."
1472                 exit 1
1473         fi
1474         
1475         initialize_script_paths
1476         
1477         echo "$SCRIPT_NAME will now begin checking for the programs it needs to operate. First a check of"
1478         echo "the main languages and tools $SCRIPT_NAME uses. Python is only for debugging data collection."
1479         echo $Line
1480         echo "Bash version: $( bash --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU bash/ {print $4}' )"
1481         if [[ -n $( type -p gawk ) ]];then
1482                 gawk_version=$( gawk --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU Awk/ {print $3}' )
1483         fi
1484         if [[ -n $( type -p sed ) ]];then
1485                 sed_version=$( sed --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^GNU sed version/ {print $4}' )
1486         fi
1487         if [[ -n $( type -p sudo ) ]];then
1488                 sudo_version=$( sudo -V 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Sudo version/ {print $3}' )
1489         fi
1490         if [[ -n $( type -p python ) ]];then
1491                 python_version=$( python --version 2>&1 | awk 'BEGIN {IGNORECASE=1} /^Python/ {print $2}' )
1492         fi
1493         echo "Gawk version: $gawk_version"
1494         echo "Sed version: $sed_version"
1495         echo "Sudo version: $sudo_version"
1496         echo "Python version: $python_version"
1497         echo $Line
1498         echo "Test One: Required System Directories."
1499         echo "If one of these system directories is missing, $SCRIPT_NAME cannot operate:"
1500         echo 
1501         check_recommends_items 'required-dirs'
1502         echo "Test Two: Required Core Applications."
1503         echo "If one of these applications is missing, $SCRIPT_NAME cannot operate:"
1504         echo 
1505         check_recommends_items 'required-apps'
1506         echo 'Test Three: Script Recommends for Graphics Features. If you do not use X these do not matter.'
1507         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1508         echo 
1509         check_recommends_items 'recommended-x-apps'
1510         echo 'Test Four: Script Recommends for Remaining Features.' 
1511         echo "If one of these applications is missing, $SCRIPT_NAME will have incomplete output:"
1512         echo 
1513         check_recommends_items 'recommended-apps'
1514         echo 'Test Five: System Directories for Various Information.' 
1515         echo "If one of these directories is missing, $SCRIPT_NAME will have incomplete output:"
1516         echo 
1517         check_recommends_items 'system-dirs'
1518         echo 'All tests completed.' 
1519 }
1520 # args: $1 - check item
1521 check_recommends_items()
1522 {
1523         local item='' item_list='' item_string='' missing_items='' missing_string=''
1524         local package='' application='' feature='' type='' starter='' finisher=''
1525         local package_deb='' package_pacman='' package_rpm='' 
1526         local print_string='' separator=''
1527         local required_dirs='/proc /sys'
1528         # package-owner: 1 - debian/ubuntu; 2 - arch; 3 - yum/rpm
1529         # pardus: pisi sf -q /usr/bin/package
1530         local required_apps='
1531         df:coreutils~coreutils~coreutils~:partition_data 
1532         free:procps~procps~procps~:system_memory 
1533         gawk:gawk~gawk~gawk~:core_tool
1534         grep:grep~grep~grep~:string_search 
1535         lspci:pciutils~pciutils~pciutils~:hardware_data 
1536         ps:procps~procps~procps~:process_data 
1537         readlink:coreutils~coreutils~coreutils~: 
1538         sed:sed~sed~sed~:string_replace 
1539         tr:coreutils~coreutils~coreutils~:character_replace 
1540         uname:uname~coreutils~coreutils~:kernel_data 
1541         uptime:procps~procps~procps~: 
1542         wc:coreutils~coreutils~coreutils~:word_character_count
1543         '
1544         local x_recommends='
1545         glxinfo:mesa-utils~mesa-demos~glx-utils~:-G_glx_info 
1546         xdpyinfo:X11-utils~xorg-xdpyinfo~xorg-x11-utils~:-G_multi_screen_resolution 
1547         xprop:X11-utils~xorg-xprop~x11-utils~:-S_desktop_data 
1548         xrandr:x11-xserver-utils~xrandr~x11-server-utils~:-G_single_screen_resolution
1549         '
1550         local recommended_apps='
1551         file:file~file~file~:-o_unmounted_file_system
1552         hddtemp:hddtemp~hddtemp~hddtemp~:-Dx_show_hdd_temp 
1553         ifconfig:net-tools~net-tools~net-tools~:-i_ip_lan-deprecated
1554         ip:iproute~iproute2~iproute~:-i_ip_lan
1555         sensors:lm-sensors~lm_sensors~lm-sensors~:-s_sensors_output
1556         lsusb:usbutils~usbutils~usbutils~:-A_usb_audio;-N_usb_networking 
1557         modinfo:module-init-tools~module-init-tools~module-init-tools~:-Ax,-Nx_module_version 
1558         runlevel:sysvinit~sysvinit~systemd~:-I_runlevel
1559         sudo:sudo~sudo~sudo~:-Dx_hddtemp-user;-o_file-user
1560         '
1561         local recommended_dirs='
1562         /sys/class/dmi/id:-M_system,_motherboard,_bios
1563         /dev:-l,-u,-o,-p,-P,-D_disk_partition_data
1564         /dev/disk/by-label:-l,-o,-p,-P_partition_labels
1565         /dev/disk/by-uuid:-u,-o,-p,-P_partition_uuid
1566         '
1567         
1568         case $1 in
1569                 required-dirs)
1570                         item_list=$required_dirs
1571                         item_string='Required file system'
1572                         missing_string='system directories'
1573                         type='directories'
1574                         ;;
1575                 required-apps)
1576                         item_list=$required_apps
1577                         item_string='Required application'
1578                         missing_string='applications, and their corresponding packages,'
1579                         type='applications'
1580                         ;;
1581                 recommended-x-apps)
1582                         item_list=$x_recommends
1583                         item_string='Recommended X application'
1584                         missing_string='applications, and their corresponding packages,'
1585                         type='applications'
1586                         ;;
1587                 recommended-apps)
1588                         item_list=$recommended_apps
1589                         item_string='Recommended application'
1590                         missing_string='applications, and their corresponding packages,'
1591                         type='applications'
1592                         ;;
1593                 system-dirs)
1594                         item_list=$recommended_dirs
1595                         item_string='System directory'
1596                         missing_string='system directories'
1597                         type='directories'
1598                         ;;
1599         esac
1600         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
1601         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
1602         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
1603         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
1604         
1605         for item in $item_list
1606         do
1607                 if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 0 ]];then
1608                         application=$item
1609                         package=''
1610                         feature=''
1611                         location=''
1612                 elif [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 1 ]];then
1613                         application=$( cut -d ':' -f 1 <<< $item )
1614                         package=''
1615                         feature=$( cut -d ':' -f 2 <<< $item )
1616                         location=''
1617                 else
1618                         application=$( cut -d ':' -f 1 <<< $item )
1619                         package=$( cut -d ':' -f 2 <<< $item )
1620                         location=$( type -p $application )
1621                         if [[ $( awk -F ":" '{print NF-1}' <<< $item ) -eq 2 ]];then
1622                                 feature=$( cut -d ':' -f 3 <<< $item )
1623                         else
1624                                 feature=''
1625                         fi
1626                 fi
1627                 if [[ -n $feature ]];then
1628                         print_string="$item_string: $application (info: $( sed 's/_/ /g' <<< $feature ))"
1629                 else
1630                         print_string="$item_string: $application"
1631                 fi
1632                 starter="$( sed -e :a -e 's/^.\{1,75\}$/&./;ta' <<< $print_string )"
1633                 if [[ -z $( grep '^/' <<< $application ) && -n $location ]] || [[ -d $application ]];then
1634                         if [[ -n $location ]];then
1635                                 finisher=" $location"
1636                         else
1637                                 finisher=" Present"
1638                         fi
1639                 else
1640                         finisher=" Missing"
1641                         missing_items="$missing_items$separator$application:$package"
1642                         separator=' '
1643                 fi
1644                 
1645                 echo "$starter$finisher"
1646         done
1647         echo 
1648         if [[ -n $missing_items ]];then
1649                 echo "The following $type are missing from your system:"
1650                 for item in $missing_items
1651                 do
1652                         application=$( cut -d ':' -f 1 <<< $item )
1653                         if [[ $type == 'applications' ]];then
1654                                 # echo '--------------------------------------------------------'
1655                                 echo
1656                                 package=$( cut -d ':' -f 2 <<< $item )
1657                                 package_deb=$( cut -d '~' -f 1 <<< $package )
1658                                 package_pacman=$( cut -d '~' -f 2 <<< $package )
1659                                 package_rpm=$( cut -d '~' -f 3 <<< $package )
1660                                 echo "Application: $application"
1661                                 echo "To add to your system, install the proper distribution package for your system:"
1662                                 echo "Debian/Ubuntu: $package_deb :: Arch Linux: $package_pacman :: Redhat/Fedora/Suse: $package_rpm"
1663                         else
1664                                 echo "Directory: $application"
1665                         fi
1666                 done
1667                 if [[ $item_string == 'System directory' ]];then
1668                         echo "These directories are created by the kernel, so don't worry if they are not present."
1669                 fi
1670         else
1671                 echo "All the $( cut -d ' ' -f 1 <<< $item_string | sed -e 's/Re/re/' -e 's/Sy/sy/' ) $type are present."
1672         fi
1673         echo $Line
1674 }
1675
1676 #### -------------------------------------------------------------------
1677 #### print / output cleaners
1678 #### -------------------------------------------------------------------
1679
1680 # inxi speaks through here. When run by Konversation script alias mode, uses DCOP
1681 # for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e
1682 # note: dcop does not seem able to handle \n so that's being stripped out and replaced with space.
1683 print_screen_output()
1684 {
1685         eval $LOGFS
1686         # the double quotes are needed to avoid losing whitespace in data when certain output types are used
1687         local print_data="$( echo -e "$1" )"
1688
1689         # just using basic debugger stuff so you can tell which thing is printing out the data. This
1690         # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off
1691         # the redundant debugger output which as far as I can tell does exactly nothing to help debugging.
1692         if [[ $DEBUG -gt 5 ]];then
1693                 if [[ $KONVI -eq 1 ]];then
1694                         # konvi doesn't seem to like \n characters, it just prints them literally
1695                         # print_data="$( tr '\n' ' ' <<< "$print_data" )"
1696                         # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'"
1697                         print_data="KP-$KONVI: $print_data"
1698                 elif [[ $KONVI -eq 2 ]];then
1699                         # echo "konvi='$KONVI' saying : '$print_data'"
1700                         print_data="KP-$KONVI: $print_data"
1701                 else
1702                         # echo "printing out: '$print_data'"
1703                         print_data="P: $print_data"
1704                 fi
1705         fi
1706
1707         if [[ $KONVI -eq 1 && $B_DCOP == 'true' ]]; then ## dcop Konversation (<= 1.1 (qt3))
1708                 # konvi doesn't seem to like \n characters, it just prints them literally
1709                 $print_data="$( tr '\n' ' ' <<< "$print_data" )"
1710                 dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data"
1711
1712         elif [[ $KONVI -eq 3 && $B_QDBUS == 'true' ]]; then ## dbus Konversation (> 1.2 (qt4))
1713                 qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data"
1714
1715 #       elif [[ $IRC_CLIENT == 'X-Chat' ]]; then
1716 #               qdbus org.xchat.service print "$print_data\n"
1717
1718         else
1719                 # the -n is needed to avoid double spacing of output in terminal
1720                 echo -ne "$print_data\n"
1721         fi
1722         eval $LOGFE
1723 }
1724
1725 ## this handles all verbose line construction with indentation/line starter
1726 ## args: $1 - null (, actually: " ") or line starter; $2 - line content
1727 create_print_line()
1728 {
1729         eval $LOGFS
1730         printf "${C1}%-${INDENT}s${C2} %s" "$1" "$2"
1731         eval $LOGFE
1732 }
1733
1734 # this removes newline and pipes.
1735 # args: $1 - string to clean
1736 remove_erroneous_chars()
1737 {
1738         eval $LOGFS
1739         ## RS is input record separator
1740         ## gsub is substitute;
1741         gawk '
1742         BEGIN {
1743                 RS=""
1744         }
1745         {
1746                 gsub(/\n$/,"")         ## (newline; end of string) with (nothing)
1747                 gsub(/\n/," ");        ## (newline) with (space)
1748                 gsub(/^ *| *$/, "")    ## (pipe char) with (nothing)
1749                 gsub(/  +/, " ")       ## ( +) with (space)
1750                 gsub(/ [ ]+/, " ")     ## ([ ]+) with (space)
1751                 gsub(/^ +| +$/, "")    ## (pipe char) with (nothing)
1752                 printf $0
1753         }' "$1"      ## prints (returns) cleaned input
1754         eval $LOGFE
1755 }
1756
1757 #### -------------------------------------------------------------------
1758 #### parameter handling, print usage functions.
1759 #### -------------------------------------------------------------------
1760
1761 # Get the parameters. Note: standard options should be lower case, advanced or testing, upper
1762 # args: $1 - full script startup args: $@
1763 get_parameters()
1764 {
1765         eval $LOGFS
1766         local opt='' wget_test='' update_flags='U!:' debug_data_type='' 
1767         local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false
1768
1769         # If distro maintainers want to not allow updates, turn off that option for users
1770         if [[ $B_ALLOW_UPDATE == 'false' ]];then
1771                 update_flags=''
1772         fi
1773         if [[ $1 == '--version' ]];then
1774                 print_version_info
1775                 exit 0
1776         elif [[ $1 == '--help' ]];then
1777                 show_options
1778                 exit 0
1779         elif [[ $1 == '--recommends' ]];then
1780                 check_recommends
1781                 exit 0
1782         # the short form only runs if no args output args are used
1783         # no need to run through these if there are no args
1784         # reserved for future use: -g for extra Graphics; -m for extra Machine; -d for extra Disk
1785         elif [[ -n $1 ]];then
1786                 while getopts Abc:CdDfFGhHiIlMnNopPrsSt:uv:VxzZ%@:${update_flags} opt
1787                 do
1788                         case $opt in
1789                         A)      B_SHOW_AUDIO='true'
1790                                 use_short='false'
1791                                 ;;
1792                         b)      use_short='false'
1793                                 B_SHOW_BASIC_CPU='true'
1794                                 B_SHOW_DISK_TOTAL='true'
1795                                 B_SHOW_GRAPHICS='true'
1796                                 B_SHOW_INFO='true'
1797                                 B_SHOW_MACHINE='true'
1798                                 B_SHOW_NETWORK='true'
1799                                 B_SHOW_SYSTEM='true'
1800                                 ;;
1801                         c)      if [[ -n $( grep -E '^[0-9][0-9]?$' <<< $OPTARG ) ]];then
1802                                         case $OPTARG in
1803                                                 99)
1804                                                         B_RUN_COLOR_SELECTOR='true'
1805                                                         COLOR_SELECTION='global'
1806                                                         ;;
1807                                                 98)
1808                                                         B_RUN_COLOR_SELECTOR='true'
1809                                                         COLOR_SELECTION='irc-console'
1810                                                         ;;
1811                                                 97)
1812                                                         B_RUN_COLOR_SELECTOR='true'
1813                                                         COLOR_SELECTION='irc-virtual-terminal'
1814                                                         ;;
1815                                                 96)
1816                                                         B_RUN_COLOR_SELECTOR='true'
1817                                                         COLOR_SELECTION='irc'
1818                                                         ;;
1819                                                 95)
1820                                                         B_RUN_COLOR_SELECTOR='true'
1821                                                         COLOR_SELECTION='virtual-terminal'
1822                                                         ;;
1823                                                 94)
1824                                                         B_RUN_COLOR_SELECTOR='true'
1825                                                         COLOR_SELECTION='console'
1826                                                         ;;
1827                                                 *)      
1828                                                         B_COLOR_SCHEME_SET='true'
1829                                                         ## note: not sure about this, you'd think user values should be overridden, but
1830                                                         ## we'll leave this for now
1831                                                         if [[ -z $COLOR_SCHEME ]];then
1832                                                                 set_color_scheme "$OPTARG"
1833                                                         fi
1834                                                         ;;
1835                                         esac
1836                                 else
1837                                         error_handler 3 "$OPTARG"
1838                                 fi
1839                                 ;;
1840                         C)      B_SHOW_CPU='true'
1841                                 use_short='false'
1842                                 ;;
1843                         d)      B_SHOW_DISK='true'
1844                                 B_SHOW_FULL_OPTICAL='true'
1845                                 use_short='false'
1846                                 # error_handler 20 "-d has been replaced by -b"
1847                                 ;;
1848                         D)      B_SHOW_DISK='true'
1849                                 use_short='false'
1850                                 ;;
1851                         f)      B_SHOW_CPU='true'
1852                                 B_CPU_FLAGS_FULL='true'
1853                                 use_short='false'
1854                                 ;;
1855                         F)      # B_EXTRA_DATA='true'
1856                                 B_SHOW_ADVANCED_NETWORK='true'
1857                                 B_SHOW_AUDIO='true'
1858                                 # B_SHOW_BASIC_OPTICAL='true'
1859                                 B_SHOW_CPU='true'
1860                                 B_SHOW_DISK='true'
1861                                 B_SHOW_GRAPHICS='true'
1862                                 B_SHOW_INFO='true'
1863                                 B_SHOW_MACHINE='true'
1864                                 B_SHOW_NETWORK='true'
1865                                 B_SHOW_PARTITIONS='true'
1866                                 B_SHOW_SENSORS='true'
1867                                 B_SHOW_SYSTEM='true'
1868                                 use_short='false'
1869                                 ;;
1870                         G)      B_SHOW_GRAPHICS='true'
1871                                 use_short='false'
1872                                 ;;
1873                         i)      B_SHOW_IP='true'
1874                                 B_SHOW_NETWORK='true'
1875                                 B_SHOW_ADVANCED_NETWORK='true'
1876                                 use_short='false'
1877                                 ;;
1878                         I)      B_SHOW_INFO='true'
1879                                 use_short='false'
1880                                 ;;
1881                         l)      B_SHOW_LABELS='true'
1882                                 B_SHOW_PARTITIONS='true'
1883                                 use_short='false'
1884                                 ;;
1885                         M)      B_SHOW_MACHINE='true'
1886                                 use_short='false'
1887                                 ;;
1888                         n)      B_SHOW_ADVANCED_NETWORK='true'
1889                                 B_SHOW_NETWORK='true'
1890                                 use_short='false'
1891                                 ;;
1892                         N)      B_SHOW_NETWORK='true'
1893                                 use_short='false'
1894                                 ;;
1895                         o)      B_SHOW_UNMOUNTED_PARTITIONS='true'
1896                                 use_short='false'
1897                                 ;;
1898                         p)      B_SHOW_PARTITIONS_FULL='true'
1899                                 B_SHOW_PARTITIONS='true'
1900                                 use_short='false'
1901                                 ;;
1902                         P)      B_SHOW_PARTITIONS='true'
1903                                 use_short='false'
1904                                 ;;
1905                         r)      B_SHOW_REPOS='true'
1906                                 use_short='false'
1907                                 ;;
1908                         s)      B_SHOW_SENSORS='true'
1909                                 use_short='false'
1910                                 ;;
1911                         S)      B_SHOW_SYSTEM='true'
1912                                 use_short='false'
1913                                 ;;
1914                         t)      if [[ -n $( grep -E '^(c|m|cm|mc)([1-9]|1[0-9]|20)?$' <<< $OPTARG ) ]];then
1915                                         use_short='false'
1916                                         if [[ -n $( grep -E '[0-9]+' <<< $OPTARG ) ]];then
1917                                                 PS_COUNT=$( grep -Eo '[0-9]+' <<< $OPTARG )
1918                                         fi
1919                                         if [[ -n $( grep 'c' <<< $OPTARG ) ]];then
1920                                                 B_SHOW_PS_CPU_DATA='true'
1921                                         fi
1922                                         if [[ -n $( grep 'm' <<< $OPTARG ) ]];then
1923                                                 B_SHOW_PS_MEM_DATA='true'
1924                                         fi
1925                                 else
1926                                         error_handler 13 "$OPTARG"
1927                                 fi
1928                                 ;;
1929                         u)      B_SHOW_UUIDS='true'
1930                                 B_SHOW_PARTITIONS='true'
1931                                 use_short='false'
1932                                 ;;
1933                         v)      if [[ -n $( grep -E "^[0-9][0-9]?$" <<< $OPTARG ) && $OPTARG -le $VERBOSITY_LEVELS ]];then
1934                                         if [[ $OPTARG -ge 1 ]];then
1935                                                 use_short='false'
1936                                                 B_SHOW_BASIC_CPU='true'
1937                                                 B_SHOW_DISK_TOTAL='true'
1938                                                 B_SHOW_GRAPHICS='true'
1939                                                 B_SHOW_INFO='true'
1940                                                 B_SHOW_SYSTEM='true'
1941                                         fi
1942                                         if [[ $OPTARG -ge 2 ]];then
1943                                                 B_SHOW_BASIC_DISK='true'
1944                                                 B_SHOW_MACHINE='true'
1945                                                 B_SHOW_NETWORK='true'
1946                                         fi
1947                                         if [[ $OPTARG -ge 3 ]];then
1948                                                 B_SHOW_ADVANCED_NETWORK='true'
1949                                                 B_SHOW_CPU='true'
1950                                                 B_EXTRA_DATA='true'
1951                                         fi
1952                                         if [[ $OPTARG -ge 4 ]];then
1953                                                 B_SHOW_DISK='true'
1954                                                 B_SHOW_PARTITIONS='true'
1955                                         fi
1956                                         if [[ $OPTARG -ge 5 ]];then
1957                                                 B_SHOW_AUDIO='true'
1958                                                 B_SHOW_BASIC_OPTICAL='true'
1959                                                 B_SHOW_SENSORS='true'
1960                                                 B_SHOW_LABELS='true'
1961                                                 B_SHOW_UUIDS='true'
1962                                         fi
1963                                         if [[ $OPTARG -ge 6 ]];then
1964                                                 B_SHOW_FULL_OPTICAL='true'
1965                                                 B_SHOW_PARTITIONS_FULL='true'
1966                                                 B_SHOW_UNMOUNTED_PARTITIONS='true'
1967                                         fi
1968                                         if [[ $OPTARG -ge 7 ]];then
1969                                                 B_EXTRA_EXTRA_DATA='true'
1970                                                 B_SHOW_IP='true'
1971                                         fi
1972                                 else
1973                                         error_handler 4 "$OPTARG"
1974                                 fi
1975                                 ;;
1976                         U)      script_self_updater "$SCRIPT_DOWNLOAD" 'svn server'
1977                                 ;;
1978                         V)      print_version_info
1979                                 exit 0
1980                                 ;;
1981                         # this will trigger either with xx or with Fx but not with xF
1982                         x)      if [[ $B_EXTRA_DATA == 'true' ]];then
1983                                         B_EXTRA_EXTRA_DATA='true'
1984                                 fi
1985                                 B_EXTRA_DATA='true'
1986                                 ;;
1987                         z)      B_OUTPUT_FILTER='true'
1988                                 ;;
1989                         Z)      B_OVERRIDE_FILTER='true'
1990                                 ;;
1991                         h)      show_options
1992                                 exit 0
1993                                 ;;
1994                         H)      show_options 'full'
1995                                 exit 0
1996                                 ;;
1997                         ## debuggers and testing tools
1998                         %)      B_HANDLE_CORRUPT_DATA='true'
1999                                 ;;
2000                         @)      if [[ -n $( grep -E "^([1-9]|1[0-4])$" <<< $OPTARG ) ]];then
2001                                         DEBUG=$OPTARG
2002                                         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
2003                                                 B_UPLOAD_DEBUG_DATA='true'
2004                                         fi
2005                                         exec 2>&1
2006                                         # switch on logging only for -@ 8-10
2007                                         case $OPTARG in
2008                                                 8|9|10)
2009                                                         if [[ $OPTARG -eq 10 ]];then
2010                                                                 B_LOG_COLORS='true'
2011                                                         elif [[ $OPTARG -eq 9 ]];then           
2012                                                                 B_LOG_FULL_DATA='true'
2013                                                         fi
2014                                                         B_USE_LOGGING='true'
2015                                                         # pack the logging data for evals function start/end
2016                                                         LOGFS=$LOGFS_STRING
2017                                                         LOGFE=$LOGFE_STRING
2018                                                         create_rotate_logfiles # create/rotate logfiles before we do anything else
2019                                                         ;;
2020                                                 11|12|13|14)
2021                                                         case $OPTARG in
2022                                                                 11)
2023                                                                         debug_data_type='sys'
2024                                                                         ;;
2025                                                                 12)
2026                                                                         debug_data_type='xorg'
2027                                                                         ;;
2028                                                                 13)
2029                                                                         debug_data_type='disk'
2030                                                                         ;;
2031                                                                 14)
2032                                                                         debug_data_type='all'
2033                                                                         ;;
2034                                                         esac
2035                                                         initialize_script_data
2036                                                         debug_data_collector $debug_data_type
2037                                                         ;;
2038                                         esac
2039                                 else
2040                                         error_handler 9 "$OPTARG"
2041                                 fi
2042                                 ;;
2043                         !)      # test for various supported methods
2044                                 case $OPTARG in
2045                                         1)      B_TESTING_1='true'
2046                                                 ;;
2047                                         2)      B_TESTING_2='true'
2048                                                 ;;
2049                                         3)      B_TESTING_1='true'
2050                                                 B_TESTING_2='true'
2051                                                 ;;
2052                                         10)
2053                                                 script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server'
2054                                                 ;;
2055                                         11)
2056                                                 script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server'
2057                                                 ;;
2058                                         12)
2059                                                 script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server'
2060                                                 ;;
2061                                         13)
2062                                                 script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server'
2063                                                 ;;
2064                                         14)
2065                                                 script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server'
2066                                                 ;;
2067                                         ftp*)
2068                                                 ALTERNATE_FTP="$OPTARG"
2069                                                 ;;
2070                                         http*)
2071                                                 script_self_updater "$OPTARG" 'alt server'
2072                                                 ;;
2073                                         *)      error_handler 11 "$OPTARG"
2074                                                 ;;
2075                                 esac
2076                                 ;;
2077                         *)      error_handler 7 "$1"
2078                                 ;;
2079                         esac
2080                 done
2081         fi
2082         ## this must occur here so you can use the debugging flag to show errors
2083         ## Reroute all error messages to the bitbucket (if not debugging)
2084         if [[ $DEBUG -eq 0 ]];then
2085                 exec 2>/dev/null
2086         fi
2087         #((DEBUG)) && exec 2>&1 # This is for debugging konversation
2088
2089         # after all the args have been processed, if no long output args used, run short output
2090         if [[ $use_short == 'true' ]];then
2091                 B_SHOW_SHORT_OUTPUT='true'
2092         fi
2093         # just in case someone insists on using -zZ
2094         if [[ $B_OVERRIDE_FILTER == 'true' ]];then
2095                 B_OUTPUT_FILTER='false'
2096         fi
2097         eval $LOGFE
2098 }
2099
2100 ## print out help menu, not including Testing or Debugger stuff because it's not needed
2101 show_options()
2102 {
2103         local color_scheme_count=$(( ${#A_COLOR_SCHEMES[@]} - 1 ))
2104         
2105         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
2106                 print_screen_output "Sorry, you can't run the help option in an IRC client."
2107                 exit 1
2108         fi
2109         print_screen_output "$SCRIPT_NAME supports the following options. You can combine them, or list them"
2110         print_screen_output "one by one: Examples: $SCRIPT_NAME -v4 -c6 OR $SCRIPT_NAME -bDc 6"
2111         print_screen_output " "
2112         print_screen_output "If you start $SCRIPT_NAME with no arguments, it will show the short form."
2113         print_screen_output "The following options if used without -F, -b, or -v will show just the complete line(s):"
2114         print_screen_output "A,C,D,G,I,M,N,P,S,f,i,n,o,p,l,u,r,s,t - you can use these alone or together to show"
2115         print_screen_output "just the line(s) you want to see."
2116         print_screen_output "If you use them with -v [level], -b or -F, it will show the full output for that line "
2117         print_screen_output "along with the output for the chosen verbosity level."
2118         print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
2119         print_screen_output "Output Control Options:"
2120         print_screen_output "-A  Show Audio/sound card information."
2121         print_screen_output "-b  Shows basic output, short form (previously -d). Same as: $SCRIPT_NAME -v 2"
2122         print_screen_output "-c  Available color schemes. Scheme number is required. Color selectors run a color selector option"
2123         print_screen_output "    prior to $SCRIPT_NAME starting which lets you set the config file value for the selection."
2124         print_screen_output "    Supported color schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11"
2125         print_screen_output "    Color selectors for each type display (NOTE: irc and global only show safe color set):"
2126         print_screen_output "    94 - Console, out of X"
2127         print_screen_output "    95 - Terminal, running in X - like xTerm"
2128         print_screen_output "    96 - Gui IRC, running in X - like Xchat, Quassel, Konversation etc."
2129         print_screen_output "    97 - Console IRC running in X - like irssi in xTerm"
2130         print_screen_output "    98 - Console IRC not in  X"
2131         print_screen_output "    99 - Global - Overrides/removes all settings. Setting specific removes global."
2132         print_screen_output "-C  Show full CPU output, including per CPU clockspeed."
2133         print_screen_output "-d  Shows optical drive data. Same as -Dd. With -x, adds features line to output. -xx adds a few more features."
2134         print_screen_output "-D  Show full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB."
2135         print_screen_output "-f  Show all cpu flags used, not just the short list. Not shown with -F to avoid spamming."
2136         print_screen_output "-F  Show Full output for $SCRIPT_NAME. Includes all Upper Case line letters, plus -s and -n."
2137         print_screen_output "    Does not show extra verbose options like -x -d -f -u -l -o -p -t -r unless you use that argument."
2138         print_screen_output "-G  Show Graphic card information (card, x type, resolution, glx renderer, version)."
2139         print_screen_output "-i  Show Wan IP address, and shows local interfaces (requires ifconfig network tool). Same as -Nni"
2140         print_screen_output "    Not shown with -F for user security reasons, you shouldn't paste your local/wan IP."
2141         print_screen_output "-I  Show Information: processes, uptime, memory, irc client, inxi version."
2142         print_screen_output "-l  Show partition labels. Default: short partition -P. For full -p output, use: -pl (or -plu)."
2143         print_screen_output "-M  Show machine data. Motherboard, Bios, and if present, System Builder (Like Lenovo)."
2144         print_screen_output "    Older systems/kernels without the required /sys data can use dmidecode instead, run as root."
2145         print_screen_output "-n  Show Advanced Network card information. Same as -Nn. Shows interface, speed, mac id, state, etc."
2146         print_screen_output "-N  Show Network card information. With -x, shows PCI BusID, Port number."
2147         print_screen_output "-o  Show unmounted partition information (includes UUID and LABEL if available)."
2148         print_screen_output "    Shows file system type if you have file installed, if you are root OR if you have"
2149         print_screen_output "    added to /etc/sudoers (sudo v. 1.7 or newer): <username> ALL = NOPASSWD: /usr/bin/file (sample)"
2150         print_screen_output "-p  Show full partition information (-P plus all other detected partitions)."
2151         print_screen_output "-P  Show Partition information (shows what -v 4 would show, but without extra data)."
2152         print_screen_output "    Shows, if detected: / /boot /home /tmp /usr /var. Use -p to see all mounted partitions."
2153         print_screen_output "-r  Show distro repository data. Currently supported repo types: APT; PACMAN; PISI; YUM."
2154         print_screen_output "-s  Show sensors output (if sensors installed/configured): mobo/cpu/gpu temp; detected fan speeds."
2155         print_screen_output "    Gpu temp only for Fglrx/Nvidia drivers. Nvidia shows screen number for > 1 screens."
2156         print_screen_output "-S  Show System information: host name, kernel, desktop environment (if in X), distro"
2157         print_screen_output "-t  Show processes. Requires extra options: c (cpu) m (memory) cm (cpu+memory). If followed by numbers 1-20,"
2158         print_screen_output "    shows that number of processes for each type (default: $PS_COUNT; if in irc, max: 5): -t cm10"
2159         print_screen_output "    Make sure to have no space between letters and numbers (-t cm10 -right, -t cm 10 -wrong)."
2160         print_screen_output "-u  Show partition UUIDs. Default: short partition -P. For full -p output, use: -pu (or -plu)."
2161         print_screen_output "-v  Script verbosity levels. Verbosity level number is required. Should not be used with -b or -F"
2162         print_screen_output "    Supported levels: 0-${VERBOSITY_LEVELS} Example: $SCRIPT_NAME -v 4"
2163         print_screen_output "    0 - Short output, same as: $SCRIPT_NAME"
2164         print_screen_output "    1 - Basic verbose, -S + basic CPU + -G + basic Disk + -I."
2165         print_screen_output "    2 - Adds networking card (-N), Machine (-M) data, and shows basic hard disk data (names only)."
2166         print_screen_output "        Same as: $SCRIPT_NAME -b"
2167         print_screen_output "    3 - Adds advanced CPU (-C), network (-n) data, and switches on -x advanced data option."
2168         print_screen_output "    4 - Adds partition size/filled data (-P) for (if present):/, /home, /var/, /boot"
2169         print_screen_output "        Shows full disk data (-D)"
2170         print_screen_output "    5 - Adds audio card (-A); sensors (-s), partion label (-l) and UUID (-u), short form of optical drives."
2171         print_screen_output "    6 - Adds full partition data (-p), unmounted partition data (-o), optical drive data (-d)."
2172         print_screen_output "    7 - Adds network IP data (-i); triggers -xx."
2173         print_screen_output "-x  Show extra data (only works with verbose or line output, not short form): "
2174         print_screen_output "    -C - bogomips on Cpu;"
2175         print_screen_output "    -d - Adds items to features line of optical drive; adds rev version to optical drive."
2176         print_screen_output "    -D - Hdd temp with disk data if you have hddtemp installed, if you are root OR if you have added to"
2177         print_screen_output "         /etc/sudoers (sudo v. 1.7 or newer): <username> ALL = NOPASSWD: /usr/sbin/hddtemp (sample)"
2178         print_screen_output "    -G - Direct rendering status for Graphics (in X)."
2179         print_screen_output "    -G - (for single gpu, nvidia driver) screen number gpu is running on."
2180         print_screen_output "    -i - Show IPv6 as well for LAN interface (IF) devices."
2181         print_screen_output "    -I - Show system GCC, default. With -xx, also show other installed GCC versions."
2182         print_screen_output "    -N -A - Adds version/port(s)/driver version (if available) for Network/Audio;"
2183         print_screen_output "    -N -A -G - Network, audio, graphics, shows PCI Bus ID/Usb ID number of card;"
2184         print_screen_output "    -S - Desktop toolkit if avaliable (GNOME/XFCE/KDE only); Kernel gcc version"
2185         print_screen_output "    -t - Adds memory use output to cpu (-xt c), and cpu use to memory (-xt m)."
2186         print_screen_output "-xx Show extra, extra data (only works with verbose or line output, not short form): "
2187         print_screen_output "    -I - Adds other detected installed gcc versions to primary gcc output (if present)."
2188         print_screen_output "    -M - Adds chassis information, if any data for that is available."
2189         print_screen_output "    -xx -@ <11-14> - Automatically uploads debugger data tar.gz file to ftp.techpatterns.com."
2190         print_screen_output "-z  Adds security filters for IP addresses, Mac, and user home directory name. Default on for irc clients."
2191         print_screen_output "-Z  Absolute override for output filters. Useful for debugging networking issues in irc for example."
2192         print_screen_output " "
2193         print_screen_output "Additional Options:"
2194         print_screen_output "-h --help      This help menu."
2195         print_screen_output "-H             This help menu, plus developer options. Do not use dev options in normal operation!"
2196         print_screen_output "--recommends   Checks $SCRIPT_NAME application dependencies + recommends, and directories, then shows"
2197         print_screen_output "               what package(s) you need to install to add support for that feature."
2198         if [[ $B_ALLOW_UPDATE == 'true' ]];then
2199                 print_screen_output "-U             Auto-update script. Note: if you installed as root, you"
2200                 print_screen_output "               must be root to update, otherwise user is fine."
2201         fi
2202         print_screen_output "-V --version   $SCRIPT_NAME version information. Prints information then exits."
2203         print_screen_output " "
2204         print_screen_output "Debugging Options:"
2205         print_screen_output "-%  Overrides defective or corrupted data."
2206         print_screen_output "-@  Triggers debugger output. Requires debugging level 1-14 (8-10 - logging of data)."
2207         print_screen_output "    Less than 8 just triggers $SCRIPT_NAME debugger output on screen."
2208         print_screen_output "    1-7  - On screen debugger output"
2209         print_screen_output "    8    - Basic logging"
2210         print_screen_output "    9    - Full file/sys info logging"
2211         print_screen_output "    10   - Color logging."
2212         print_screen_output "    The following create a tar.gz file of system data, plus collecting the inxi output to file:"
2213         print_screen_output "    To automatically upload debugger data tar.gz file to ftp.techpatterns.com: inxi -xx@ <11-14>"
2214         print_screen_output "    For alternate ftp upload locations: Example: inxi -! ftp.yourserver.com/incoming -xx@ 14"
2215         print_screen_output "    11 - With data file of xiin read of /sys."
2216         print_screen_output "    12 - With xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc."
2217         print_screen_output "    13 - With data from dev, disks, partitions, etc., plus xiin data file."
2218         print_screen_output "    14 - Everything, full data collection."
2219         if [[ $1 == 'full' ]];then
2220                 print_screen_output " "
2221                 print_screen_output "Developer and Testing Options (Advanced):"
2222                 print_screen_output "-! 1 - Sets testing flag B_TESTING_1='true' to trigger testing condition 1."
2223                 print_screen_output "-! 2 - Sets testing flag B_TESTING_2='true' to trigger testing condition 2."
2224                 print_screen_output "-! 3 - Sets flags B_TESTING_1='true' and B_TESTING_2='true'."
2225                 print_screen_output "-! 10 - Triggers an update from the primary dev download server instead of svn."
2226                 print_screen_output "-! 11 - Triggers an update from svn branch one - if present, of course."
2227                 print_screen_output "-! 12 - Triggers an update from svn branch two - if present, of course."
2228                 print_screen_output "-! 13 - Triggers an update from svn branch three - if present, of course."
2229                 print_screen_output "-! 14 - Triggers an update from svn branch four - if present, of course."
2230                 print_screen_output "-! <http://......> - Triggers an update from whatever server you list."
2231                 print_screen_output "-! <ftp.......> - Changes debugging data ftp upload location to whatever you enter here."
2232                 print_screen_output "   Only used together with -xx@ 11-14, and must be used in front of that."
2233                 print_screen_output "   Example: inxi -! ftp.yourserver.com/incoming -xx@ 14"
2234                 print_screen_output " "
2235         fi
2236         print_screen_output " "
2237 }
2238
2239 ## print out version information for -V/--version
2240 print_version_info()
2241 {
2242         local last_modified=$( grep -im 1 'date:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3,$4,$5}' )
2243
2244         print_screen_output "$SCRIPT_NAME - the universal, portable, system info script for console and irc."
2245         print_screen_output "Version: $SCRIPT_VERSION_NUMBER-$SCRIPT_PATCH_NUMBER"
2246         print_screen_output "Script Last Modified: $last_modified"
2247         print_screen_output "Script Location: $SCRIPT_PATH"
2248         print_screen_output " "
2249         print_screen_output "Tested in Irssi, Xchat, Konversation, BitchX, KSirc, ircII,"
2250         print_screen_output "Gaim/Pidgin, Weechat, KVIrc, Quassel, Kopete, and others."
2251         print_screen_output " "
2252         print_screen_output "This script is a fork of Infobash 3.02, which is:"
2253         print_screen_output "Copyright (C) 2005-2007  Michiel de Boer a.k.a. locsmif"
2254         print_screen_output "Subsequent changes and modifications (after Infobash 3.02) are:"
2255         print_screen_output "Copyright (C) 2008-$(date +%y) Scott Rogers, Harald Hope, aka trash80 & h2"
2256         print_screen_output " "
2257         print_screen_output "This program is free software; you can redistribute it and/or modify"
2258         print_screen_output "it under the terms of the GNU General Public License as published by"
2259         print_screen_output "the Free Software Foundation; either version 3 of the License, or"
2260         print_screen_output "(at your option) any later version."
2261 }
2262
2263 ########################################################################
2264 #### MAIN FUNCTIONS
2265 ########################################################################
2266
2267 #### -------------------------------------------------------------------
2268 #### initial startup stuff
2269 #### -------------------------------------------------------------------
2270
2271 # Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION
2272 get_start_client()
2273 {
2274         eval $LOGFS
2275         local irc_client_path='' irc_client_path_lower='' non_native_konvi='' i=''
2276         local b_non_native_app='false' pppid='' app_working_name=''
2277         local b_qt4_konvi='false'
2278
2279         if [[ $B_RUNNING_IN_SHELL == 'true' ]];then
2280                 IRC_CLIENT='Shell'
2281                 unset IRC_CLIENT_VERSION
2282         elif [[ -n $PPID && -f /proc/$PPID/exe ]];then
2283                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2284                         B_OUTPUT_FILTER='true'
2285                 fi
2286                 irc_client_path=$( readlink /proc/$PPID/exe )
2287                 irc_client_path_lower=$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path )
2288                 app_working_name=$( basename $irc_client_path_lower )
2289                 # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients
2290                 # report themselves as perl or unknown shell. IE:  when konversation starts inxi
2291                 # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc
2292                 # note: perl can report as: perl5.10.0, so it needs wildcard handling
2293                 case $app_working_name in
2294                         bash|dash|sh|python*|perl*)     # We want to know who wrapped it into the shell or perl.
2295                                 pppid="$( ps -p $PPID -o ppid --no-headers | sed 's/ //g' )"
2296                                 if [[ -n $pppid && -f /proc/$pppid/exe ]];then
2297                                         irc_client_path="$( readlink /proc/$pppid/exe )"
2298                                         irc_client_path_lower="$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path )"
2299                                         app_working_name=$( basename $irc_client_path_lower )
2300                                         b_non_native_app='true'
2301                                 fi
2302                                 ;;
2303                 esac
2304                 # replacing loose detection with tight detection, bugs will be handled with app names
2305                 # as they appear.
2306                 case $app_working_name in
2307                         # check for shell first
2308                         bash|dash|sh)
2309                                 unset IRC_CLIENT_VERSION
2310                                 IRC_CLIENT="Shell wrapper"
2311                                 ;;
2312                         # now start on irc clients, alphabetically
2313                         bitchx)
2314                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk '
2315                                 /Version/ {
2316                                         a=tolower($2)
2317                                         gsub(/[()]|bitchx-/,"",a)
2318                                         print a
2319                                         exit
2320                                 }
2321                                 $2 == "version" {
2322                                         a=tolower($3)
2323                                         sub(/bitchx-/,"",a)
2324                                         print a
2325                                         exit
2326                                 }' )"
2327                                 B_CONSOLE_IRC='true'
2328                                 IRC_CLIENT="BitchX"
2329                                 ;;
2330                         finch)
2331                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2332                                         print $2
2333                                 }' )"
2334                                 B_CONSOLE_IRC='true'
2335                                 IRC_CLIENT="Finch"
2336                                 ;;
2337                         gaim)
2338                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2339                                         print $2
2340                                 }' )"
2341                                 IRC_CLIENT="Gaim"
2342                                 ;;
2343                         ircii)
2344                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2345                                         print $3
2346                                 }' )"
2347                                 B_CONSOLE_IRC='true'
2348                                 IRC_CLIENT="ircII"
2349                                 ;;
2350                         irssi-text|irssi)
2351                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2352                                         print $2
2353                                 }' )"
2354                                 B_CONSOLE_IRC='true'
2355                                 IRC_CLIENT="Irssi"
2356                                 ;;
2357                         konversation) ## konvi < 1.2 (qt4)
2358                                 # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script
2359                                 if [[ $b_non_native_app == 'true' ]];then  ## true negative is confusing
2360                                         KONVI=2
2361                                 else # if native app
2362                                         KONVI=1
2363                                 fi
2364                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk '
2365                                 /Konversation:/ {
2366                                         for ( i=2; i<=NF; i++ ) {
2367                                                 if (i == NF) {
2368                                                         print $i
2369                                                 }
2370                                                 else {
2371                                                         printf $i" "
2372                                                 }
2373                                         }
2374                                         exit
2375                                 }' )"
2376
2377                                 T=($IRC_CLIENT_VERSION)
2378                                 if [[ ${T[0]} == *+* ]];then
2379                                         # < Sho_> locsmif: The version numbers of SVN versions look like this:
2380                                         #         "<version number of last release>+ #<build number", i.e. "1.0+ #3177" ...
2381                                         #         for releases we remove the + and build number, i.e. "1.0" or soon "1.0.1"
2382                                         IRC_CLIENT_VERSION=" CVS $IRC_CLIENT_VERSION"
2383                                         T2="${T[0]/+/}"
2384                                 else
2385                                         IRC_CLIENT_VERSION=" ${T[0]}"
2386                                         T2="${T[0]}"
2387                                 fi
2388                                 # Remove any dots except the first, and make sure there are no trailing zeroes,
2389                                 T2=$( echo "$T2" | gawk '{
2390                                         sub(/\./, " ")
2391                                         gsub(/\./, "")
2392                                         sub(/ /, ".")
2393                                         printf("%g\n", $0)
2394                                 }' )
2395                                 # Since Konversation 1.0, the DCOP interface has changed a bit: dcop "$DCPORT" Konversation ..etc
2396                                 # becomes : dcop "$DCPORT" default ... or dcop "$DCPORT" irc ..etc. So we check for versions smaller
2397                                 # than 1 and change the DCOP parameter/object accordingly.
2398                                 if [[ ${T2} -lt 1 ]];then
2399                                         DCOPOBJ="Konversation"
2400                                 fi
2401                                 IRC_CLIENT="Konversation"
2402                                 ;;
2403                         kopete)
2404                                 IRC_CLIENT_VERSION=" $( kopete -v | gawk '
2405                                 /Kopete:/ {
2406                                         print $2
2407                                         exit
2408                                 }' )"
2409                                 IRC_CLIENT="Kopete"
2410                                 ;;
2411                         kvirc)
2412                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v 2>&1 | gawk '{
2413                                         for ( i=2; i<=NF; i++) {
2414                                                 if ( i == NF ) {
2415                                                         print $i
2416                                                 }
2417                                                 else {
2418                                                         printf $i" "
2419                                                 }
2420                                         }
2421                                         exit
2422                                  }' )"
2423                                 IRC_CLIENT="KVIrc"
2424                                 ;;
2425                         pidgin)
2426                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2427                                         print $2
2428                                 }' )"
2429                                 IRC_CLIENT="Pidgin"
2430                                 ;;
2431                         quassel*)
2432                                 # sample: quassel -v
2433                                 # Qt: 4.5.0
2434                                 # KDE: 4.2.65 (KDE 4.2.65 (KDE 4.3 >= 20090226))
2435                                 # Quassel IRC: v0.4.0 [+60] (git-22effe5)
2436                                 # note: early < 0.4.1 quassels do not have -v
2437                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v 2>/dev/null | gawk -F ': ' '
2438                                 BEGIN {
2439                                         IGNORECASE=1
2440                                         clientVersion=""
2441                                 }
2442                                 /Quassel IRC/ {
2443                                         clientVersion = $2
2444                                 }
2445                                 END {
2446                                         # this handles pre 0.4.1 cases with no -v
2447                                         if ( clientVersion == "" ) {
2448                                                 clientVersion = "(pre v0.4.1)"
2449                                         }
2450                                         print clientVersion
2451                                 }' )"
2452                                 # now handle primary, client, and core. quasselcore doesn't actually
2453                                 # handle scripts with exec, but it's here just to be complete
2454                                 case $app_working_name in
2455                                         quassel)
2456                                                 IRC_CLIENT="Quassel [M]"
2457                                                 ;;
2458                                         quasselclient)
2459                                                 IRC_CLIENT="Quassel"
2460                                                 ;;
2461                                         quasselcore)
2462                                                 IRC_CLIENT="Quassel (core)"
2463                                                 ;;
2464                                 esac
2465                                 ;;
2466                         weechat-curses)
2467                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v ) "
2468                                 B_CONSOLE_IRC='true'
2469                                 IRC_CLIENT="Weechat"
2470                                 ;;
2471                         xchat-gnome)
2472                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2473                                         print $2
2474                                 }' )"
2475                                 IRC_CLIENT="X-Chat-Gnome"
2476                                 ;;
2477                         xchat)
2478                                 IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 {
2479                                         print $2
2480                                 }' )"
2481                                 IRC_CLIENT="X-Chat"
2482                                 ;;
2483                         # then do some perl type searches, do this last since it's a wildcard search
2484                         perl*|ksirc|dsirc)
2485                                 unset IRC_CLIENT_VERSION
2486                                 # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client
2487                                 get_cmdline $PPID
2488                                 for (( i=0; i <= $CMDL_MAX; i++ ))
2489                                 do
2490                                         case ${A_CMDL[i]} in
2491                                                 *dsirc*)
2492                                                 IRC_CLIENT="KSirc"
2493                                                 # Dynamic runpath detection is too complex with KSirc, because KSirc is started from
2494                                                 # kdeinit. /proc/<pid of the grandparent of this process>/exe is a link to /usr/bin/kdeinit
2495                                                 # with one parameter which contains parameters separated by spaces(??), first param being KSirc.
2496                                                 # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed,
2497                                                 # dsirc is the program that runs inxi, therefore that is the parent process that we see.
2498                                                 # You can imagine how hosed I am if I try to make inxi find out dynamically with which path
2499                                                 # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material.
2500                                                 # (KSirc sucks anyway ;)
2501                                                 IRC_CLIENT_VERSION=" $( ksirc -v | gawk '
2502                                                 /KSirc:/ {
2503                                                         print $2
2504                                                         exit
2505                                                 }' )"
2506                                                 break
2507                                                 ;;
2508                                         esac
2509                                 done
2510                                 B_CONSOLE_IRC='true'
2511                                 set_perl_python_konvi "$app_working_name"
2512                                 ;;
2513                         python*)
2514                                 # B_CONSOLE_IRC='true' # are there even any python type console irc clients? check.
2515                                 set_perl_python_konvi "$app_working_name"
2516                                 ;;
2517                         # then unset, set unknown data
2518                         *)      
2519                                 IRC_CLIENT="Unknown : ${irc_client_path##*/}"
2520                                 unset IRC_CLIENT_VERSION
2521                                 ;;
2522                 esac
2523                 if [[ $SHOW_IRC -lt 2 ]];then
2524                         unset IRC_CLIENT_VERSION
2525                 fi
2526         else
2527                 ## lets look to see if qt4_konvi is the parent.  There is no direct way to tell, so lets infer it.
2528                 ## because $PPID does not work with qt4_konvi, the above case does not work
2529                 if [[ $B_OVERRIDE_FILTER != 'true' ]];then
2530                         B_OUTPUT_FILTER='true'
2531                 fi
2532                 b_qt4_konvi=$( is_this_qt4_konvi )
2533                 if [[ $b_qt4_konvi == 'true' ]];then
2534                         KONVI=3
2535                         IRC_CLIENT='Konversation'
2536                         IRC_CLIENT_VERSION=" $( konversation -v | gawk '
2537                                 /Konversation:/ {
2538                                         for ( i=2; i<=NF; i++ ) {
2539                                                 if (i == NF) {
2540                                                         print $i
2541                                                 }
2542                                                 else {
2543                                                         printf $i" "
2544                                                 }
2545                                         }
2546                                         exit
2547                                 }' )"
2548                 else
2549                         IRC_CLIENT="PPID=\"$PPID\" - empty?"
2550                         unset IRC_CLIENT_VERSION
2551                 fi
2552         fi
2553
2554         log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID"
2555         eval $LOGFE
2556 }
2557 # args: $1 - app_working_name
2558 set_perl_python_konvi()
2559 {
2560         if [[ -z $IRC_CLIENT_VERSION ]];then
2561                 # this is a hack to try to show konversation if inxi is running but started via /cmd
2562                 if [[ -n $( ps aux | grep -i 'konversation' | grep -v 'grep' ) && $B_RUNNING_IN_X == 'true' ]];then
2563                         IRC_CLIENT='Konversation'
2564                         IRC_CLIENT_VERSION=" $( konversation --version 2>/dev/null | gawk '/^Konversation/ {print $2}' )"
2565                         B_CONSOLE_IRC='false'
2566                 else
2567                         IRC_CLIENT="Unknown $1 client"
2568                 fi
2569         fi
2570 }
2571
2572 ## try to infer the use of Konversation >= 1.2, which shows $PPID improperly
2573 ## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running,
2574 ## and all other irc clients are not running.  
2575 is_this_qt4_konvi()
2576 {
2577         local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' 
2578         local konvi='' konvi_qt4_ver='' b_is_qt4=''
2579         
2580         # fringe cases can throw error, always if untested app, use 2>/dev/null after testing if present
2581         if [[ $B_QDBUS == 'true' ]];then
2582                 konvi_dbus_exist=$( qdbus 2>/dev/null | grep "org.kde.konversation" )
2583         fi
2584          
2585         if [[ -n $konvi_dbus_exist && -e /usr/share/kde4/apps/konversation ]]; then
2586                 konvi_pid=$( ps -A | grep -i 'konversation' )
2587                 konvi_pid=$( echo $konvi_pid | gawk '{ print $1 }' ) 
2588                 konvi_home_dir=$( readlink /proc/$konvi_pid/exe )
2589                 konvi=$( echo $konvi_home_dir | sed "s/\// /g" )
2590                 konvi=($konvi)
2591
2592                 if [[ ${konvi[2]} == 'konversation' ]];then     
2593                         konvi_qt4_ver=$( konversation -v | grep -i 'konversation' )
2594                         # note: we need to change this back to a single dot number, like 1.3, not 1.3.2
2595                         konvi_qt4_client=$( echo "$konvi_qt4_ver" | gawk '{ print $2 }' | cut -d '.' -f 1,2 )
2596
2597                         if [[ $konvi_qt4_client > 1.1 ]]; then
2598                                 b_is_qt4='true'
2599                         fi
2600                 fi
2601         else
2602                 konvi_qt4="qt3"
2603                 b_is_qt4='false'
2604         fi
2605         log_function_data "b_is_qt4: $b_is_qt4"
2606         echo $b_is_qt4
2607         ## for testing this module
2608         #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]}"
2609 }
2610
2611 # This needs some cleanup and comments, not quite understanding what is happening, although generally output is known
2612 # Parse the null separated commandline under /proc/<pid passed in $1>/cmdline
2613 # args: $1 - $PPID
2614 get_cmdline()
2615 {
2616         eval $LOGFS
2617         local i=0 ppid=$1
2618
2619         if [[ ! -e /proc/$ppid/cmdline ]];then
2620                 echo 0
2621                 return
2622         fi
2623         ##print_screen_output "Marker"
2624         ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)"
2625         unset A_CMDL
2626         ## note: need to figure this one out, and ideally clean it up and make it readable
2627         while read -d $'\0' L && [[ $i -lt 32 ]]
2628         do
2629                 A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ##
2630         done < /proc/$ppid/cmdline
2631         ##print_screen_output "\$i='$i'"
2632         if [[ $i -eq 0 ]];then
2633                 A_CMDL[0]=$(< /proc/$ppid/cmdline)
2634                 if [[ -n ${A_CMDL[0]} ]];then
2635                         i=1
2636                 fi
2637         fi
2638         CMDL_MAX=$i
2639         log_function_data "CMDL_MAX: $CMDL_MAX"
2640         eval $LOGFE
2641 }
2642
2643 #### -------------------------------------------------------------------
2644 #### get data types
2645 #### -------------------------------------------------------------------
2646 ## create array of sound cards installed on system, and if found, use asound data as well
2647 get_audio_data()
2648 {
2649         eval $LOGFS
2650         local i='' alsa_data='' alsa_driver='' device_count='' temp_array=''
2651
2652         IFS=$'\n'
2653         # this first step handles the drivers for cases where the second step fails to find one
2654         device_count=$( echo "$Lspci_Data" | grep -iEc '(multimedia audio controller|audio device)' )
2655         if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
2656                 alsa_driver=$( gawk -F ']: ' '
2657                 BEGIN {
2658                         IGNORECASE=1
2659                 }
2660                 # filtering out modems and usb devices like webcams, this might get a
2661                 # usb audio card as well, this will take some trial and error
2662                 $0 !~ /modem|usb|webcam/ {
2663                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
2664                         gsub(/^ +| +$/,"",driver)
2665                         if ( driver != "" ){
2666                                 print driver
2667                         }
2668                 }' $FILE_ASOUND_DEVICE ) 
2669                 log_function_data 'cat' "$FILE_ASOUND_DEVICE"
2670         fi
2671
2672         # this is to safeguard against line breaks from results > 1, which if inserted into following
2673         # array will create a false array entry. This is a hack, not a permanent solution.
2674         alsa_driver=$( echo $alsa_driver )
2675         # now we'll build the main audio data, card name, driver, and port. If no driver is found,
2676         # and if the first method above is not null, and one card is found, it will use that instead.
2677         A_AUDIO_DATA=( $( echo "$Lspci_Data" | gawk -F ': ' -v alsaDriver="$alsa_driver" '
2678         BEGIN {
2679                 IGNORECASE=1
2680         }
2681         /multimedia audio controller|audio device/ {
2682                 audioCard=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
2683                 # The doublequotes are necessary because of the pipes in the variable.
2684                 gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard)
2685                 gsub(/,/, " ", audioCard)
2686                 gsub(/^ +| +$/, "", audioCard)
2687                 gsub(/ [ \t]+/, " ", audioCard)
2688                 aPciBusId[audioCard] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
2689                 cards[audioCard]++
2690
2691                 # loop until you get to the end of the data block
2692                 while (getline && !/^$/) {
2693                         gsub( /,/, "", $0 )
2694                         if (/driver in use/) {
2695                                 drivers[audioCard] = drivers[audioCard] gensub( /(.*): (.*)/ ,"\\2", "g" ,$0 ) ""
2696                         }
2697                         else if (/kernel modules:/) {
2698                                 modules[audioCard] = modules[audioCard] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
2699                         }
2700                         else if (/I\/O/) {
2701                                 portsTemp = gensub(/\t*I\/O ports at (.*) \[.*\]/,"\\1","g",$0)
2702                                 ports[audioCard] = ports[audioCard] portsTemp " "
2703                         }
2704                 }
2705         }
2706
2707         END {
2708                 j=0
2709                 for (i in cards) {
2710                         useDrivers=""
2711                         useModules=""
2712                         usePorts=""
2713                         usePciBusId=""
2714                          
2715                         if (cards[i]>1) {
2716                                 a[j]=cards[i]"x "i
2717                                 if (drivers[i] != "") {
2718                                         useDrivers=drivers[i]
2719                                 }
2720                         }
2721                         else {
2722                                 a[j]=i
2723                                 # little trick here to try to catch the driver if there is
2724                                 # only one card and it was null, from the first test of asound/cards
2725                                 if (drivers[i] != "") {
2726                                         useDrivers=drivers[i]
2727                                 }
2728                                 else if ( alsaDriver != "" ) {
2729                                         useDrivers=alsaDriver
2730                                 }
2731                         }
2732                         if (ports[i] != "") {
2733                                 usePorts = ports[i]
2734                         }
2735                         if (modules[i] != "" ) {
2736                                 useModules = modules[i]
2737                         }
2738                         if ( aPciBusId[i] != "" ) {
2739                                 usePciBusId = aPciBusId[i]
2740                         }
2741                         # create array primary item for master array
2742                         sub( / $/, "", usePorts ) # clean off trailing whitespace
2743                         print a[j] "," useDrivers "," usePorts "," useModules "," usePciBusId
2744                         j++
2745                 }
2746         }') )
2747
2748         # in case of failure of first check do this instead
2749         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_DEVICE_FILE == 'true' ]];then
2750                 A_AUDIO_DATA=( $( gawk -F ']: ' '
2751                 BEGIN {
2752                         IGNORECASE=1
2753                 }
2754                 $1 !~ /modem/ && $2 !~ /modem/ {
2755                         card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 )
2756                         driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 )
2757                         if ( card != "" ){
2758                                 print card","driver
2759                         }
2760                 }' $FILE_ASOUND_DEVICE ) )
2761         fi
2762         IFS="$ORIGINAL_IFS"
2763         get_audio_usb_data
2764         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
2765         if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then
2766                 A_AUDIO_DATA[0]='Failed to Detect Sound Card!'
2767         fi
2768         temp_array=${A_AUDIO_DATA[@]}
2769         log_function_data "A_AUDIO_DATA: $temp_array"
2770
2771         eval $LOGFE
2772 }
2773 # alsa usb detection by damentz
2774
2775 get_audio_usb_data()
2776 {
2777         eval $LOGFS
2778         local usb_proc_file='' array_count='' usb_data='' usb_id='' lsusb_path='' lsusb_data=''
2779         local temp_array=''
2780         
2781         IFS=$'\n'
2782         lsusb_path=$( type -p lsusb )
2783         if [[ -n $lsusb_path ]];then
2784                 lsusb_data=$( $lsusb_path 2>/dev/null )
2785         fi
2786         log_function_data 'raw' "usb_data:\n$lsusb_data"
2787         if [[ -n $lsusb_data ]];then
2788                 # for every sound card symlink in /proc/asound - display information about it
2789                 for usb_proc_file in /proc/asound/*
2790                 do
2791                         # If the file is a symlink, and contains an important usb exclusive file: continue
2792                         if [[ -L $usb_proc_file && -e $usb_proc_file/usbid  ]]; then
2793                                 # find the contents of usbid in lsusb and print everything after the 7th word on the
2794                                 # corresponding line. Finally, strip out commas as they will change the driver :)
2795                                 usb_id=$( cat $usb_proc_file/usbid )
2796                                 usb_data=$( grep "$usb_id" <<< "$lsusb_data" )
2797                                 if [[ -n $usb_data && -n $usb_id ]];then
2798                                         usb_data=$( gawk '
2799                                         BEGIN {
2800                                                 IGNORECASE=1
2801                                                 string=""
2802                                                 separator=""
2803                                         }
2804                                         {
2805                                                 gsub( /,/, " ", $0 )
2806                                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
2807                                                 gsub(/ [ \t]+/, " ", $0)
2808                                                 for ( i=7; i<= NF; i++ ) {
2809                                                         string = string separator $i
2810                                                         separator = " "
2811                                                 }
2812                                                 if ( $6 != "" ){
2813                                                         print string ",USB Audio,,," $6
2814                                                 }
2815                                         }' <<< "$usb_data" )
2816                                 fi
2817                                 # this method is interesting, it shouldn't work but it does
2818                                 #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,USB Audio,," )
2819                                 # but until we learn why the above worked, I'm using this one, which is safer
2820                                 if [[ -n $usb_data ]];then
2821                                         array_count=${#A_AUDIO_DATA[@]}
2822                                         A_AUDIO_DATA[$array_count]="$usb_data"
2823                                 fi
2824                         fi
2825                 done
2826         fi
2827         IFS="$ORIGINAL_IFS"
2828         temp_array=${A_AUDIO_DATA[@]}
2829         log_function_data "A_AUDIO_DATA: $temp_array"
2830         
2831         eval $LOGFE
2832 }
2833
2834 get_audio_alsa_data()
2835 {
2836         eval $LOGFS
2837         local alsa_data='' temp_array=''
2838
2839         # now we'll get the alsa data if the file exists
2840         if [[ $B_ASOUND_VERSION_FILE == 'true' ]];then
2841                 IFS=","
2842                 A_ALSA_DATA=( $( 
2843                 gawk '
2844                         BEGIN {
2845                                 IGNORECASE=1
2846                                 alsa=""
2847                                 version=""
2848                         }
2849                         # some alsa strings have the build date in (...)
2850                         # remove trailing . and remove possible second line if compiled by user
2851                         $0 !~ /compile/ {
2852                                 gsub( /Driver | [(].*[)]|\.$/,"",$0 )
2853                                 gsub(/,/, " ", $0)
2854                                 gsub(/^ +| +$/, "", $0)
2855                                 gsub(/ [ \t]+/, " ", $0)
2856                                 sub(/Advanced Linux Sound Architecture/, "ALSA", $0)
2857                                 if ( $1 == "ALSA" ){
2858                                         alsa=$1
2859                                 }
2860                                 version=$NF
2861                                 print alsa "," version
2862                         }' $FILE_ASOUND_VERSION 
2863                 ) )
2864                 IFS="$ORIGINAL_IFS"
2865                 log_function_data 'cat' "$FILE_ASOUND_VERSION"
2866         fi
2867         temp_array=${A_ALSA_DATA[@]}
2868         log_function_data "A_ALSA_DATA: $temp_array"
2869         eval $LOGFE
2870 }
2871
2872 get_console_irc_tty()
2873 {
2874         eval $LOGFS
2875         local tty_number=''
2876         if [[ -n ${IRC_CLIENT} ]];then
2877                 tty_number=$( ps aux | gawk '
2878                         BEGIN {
2879                                 IGNORECASE=1
2880                         }
2881                         /'${IRC_CLIENT}'/ {
2882                                 gsub(/[^0-9]/, "", $7)
2883                                 print $7
2884                         }' )
2885         fi
2886         log_function_data "tty_number: $tty_number"
2887         echo $tty_number
2888         eval $LOGFE
2889 }
2890
2891 ## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text
2892 ## return value cpu core count string, this helps resolve the multi redundant lines of old style output
2893 get_cpu_core_count()
2894 {
2895         eval $LOGFS
2896         if [[ $B_CPUINFO_FILE == 'true' ]]; then
2897                 # load the A_CPU_TYPE_PCNT_CCNT core data array
2898                 get_cpu_ht_multicore_smp_data
2899                 ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10)
2900                 # count the number of processors given
2901                 local cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]}
2902                 local cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]}
2903                 local cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]}
2904
2905                 # match the numberic value to an alpha value
2906                 case $cpu_core_count in
2907                         1) cpu_alpha_count='Single';;
2908                         2) cpu_alpha_count='Dual';;
2909                         3) cpu_alpha_count='Triple';;
2910                         4) cpu_alpha_count='Quad';;
2911                         5) cpu_alpha_count='Penta';;
2912                         6) cpu_alpha_count='Hexa';;
2913                         7) cpu_alpha_count='Hepta';;
2914                         8) cpu_alpha_count='Octa';;
2915                         9) cpu_alpha_count='Ennea';;
2916                         10) cpu_alpha_count='Deca';;
2917                         *) cpu_alpha_count='Multi';;
2918                 esac
2919                 # create array, core count integer; core count string
2920                 # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" )
2921                 A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" )
2922         fi
2923         temp_array=${A_CPU_CORE_DATA[@]}
2924         log_function_data "A_CPU_CORE_DATA: $temp_array"
2925         eval $LOGFE
2926 }
2927
2928 ## main cpu data collector
2929 get_cpu_data()
2930 {
2931         eval $LOGFS
2932         local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' temp_array=''
2933
2934         if [[ $B_CPUINFO_FILE == 'true' ]];then
2935                 # stop script for a bit to let cpu slow down before parsing cpu /proc file
2936                 sleep $CPU_SLEEP
2937                 IFS=$'\n'
2938                 A_CPU_DATA=( $( gawk -F': ' '
2939                 BEGIN {
2940                         IGNORECASE=1
2941                 }
2942                 # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+
2943                 # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES!
2944                 # Therefore PATCH to use [ \t]+ when TESTING!
2945                 /^processor[ \t]+:/ {
2946                         nr = $NF
2947                 }
2948
2949                 /^model name|^cpu\t+:/ {
2950                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF )
2951                         gsub(/'"$BAN_LIST_CPU"'/, "", $NF )
2952                         gsub(/,/, " ", $NF)
2953                         gsub(/^ +| +$/, "", $NF)
2954                         gsub(/ [ \t]+/, " ", $NF)
2955                         cpu[nr, "model"] = $NF
2956                 }
2957
2958                 /^cpu MHz|^clock\t+:/ {
2959                         if (!min) {
2960                                 min = $NF
2961                         }
2962                         else {
2963                                 if ($NF < min) {
2964                                         min = $NF
2965                                 }
2966                         }
2967
2968                         if ($NF > max) {
2969                                 max = $NF
2970                         }
2971                         gsub(/MHZ/,"",$NF) ## clears out for cell cpu
2972                         gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros
2973                         cpu[nr, "speed"] = $NF
2974                 }
2975
2976                 /^cache size/ {
2977                         cpu[nr, "cache"] = $NF
2978                 }
2979
2980                 /^flags/ {
2981                         cpu[nr, "flags"] = $NF
2982                 }
2983
2984                 /^bogomips/ {
2985                         cpu[nr, "bogomips"] = $NF
2986                 }
2987
2988                 /vendor_id/ {
2989                         gsub(/genuine|authentic/,"",$NF)
2990                         cpu[nr, "vendor"] = tolower( $NF )
2991                 }
2992
2993                 END {
2994                         #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that
2995                         for ( i = 0; i <= nr; i++ ) {
2996                                 print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] ","  cpu[nr, "vendor"]
2997                         }
2998                         if (!min) {
2999                                 print "not found"
3000                                 exit
3001                         }
3002                         if (min != max) {
3003                                 printf("Min:%s%s Max:%s%s\n", min, "Mhz", max, "Mhz")
3004                         }
3005                         else {
3006                                 printf("%s %s\n", max, "Mhz")
3007                         }
3008                 }' $FILE_CPUINFO ) )
3009                 log_function_data 'cat' "$FILE_CPUINFO"
3010         fi
3011         IFS="$ORIGINAL_IFS"
3012         temp_array=${A_CPU_DATA[@]}
3013         log_function_data "A_CPU_DATA: $temp_array"
3014         
3015         eval $LOGFE
3016 #       echo getMainCpu: ${[@]}
3017 }
3018
3019 ## this is for counting processors and finding HT types
3020 get_cpu_ht_multicore_smp_data()
3021 {
3022         eval $LOGFS
3023         # in /proc/cpuinfo
3024         local temp_array=''
3025
3026         if [[ $B_CPUINFO_FILE == 'true' ]]; then
3027                 A_CPU_TYPE_PCNT_CCNT=( $(
3028                 gawk '
3029                 BEGIN {
3030                         FS=": "
3031                         IGNORECASE = 1
3032                         num_of_cores = 0
3033                         num_of_processors = 0
3034                         num_of_cpus = 0
3035                         cpu_core_count = 0
3036                         core_id[0]
3037                         processor_id[0]
3038                         cpu_id[0]
3039                         type = "-"
3040                         iter = 0
3041                 }
3042                 # array of logical processors, both HT and physical
3043                 /^processor/ {
3044                         processor_id[iter] = $NF
3045                 }
3046                 # array of physical cpus ids
3047                 /^physical/ {
3048                         cpu_id[iter] = $NF
3049                 }
3050                 # array of core ids
3051                 /^core id/ {
3052                         core_id[iter] = $NF
3053                         iter++
3054                 }
3055                 # this will be used to fix an intel glitch if needed, cause, intel
3056                 # sometimes reports core id as the same number for each core, 0
3057                 # so if cpu cores shows greater value than number of cores, use this
3058                 /^cpu cores/ {
3059                         cpu_core_count = $NF
3060                 }
3061                 END {
3062                         ##      Look thru the array and filter same numbers.
3063                         ##      only unique numbers required
3064                         ##      this is to get an accurate count
3065                         ##      we are only concerned with array length
3066                         
3067                         i = 0
3068                         ## count unique processors ##
3069                         # note, this fails for intel cpus at times
3070                         for ( i in processor_id ) {
3071                                 procHolder[processor_id[i]] = 1
3072                         }
3073                         for ( i in procHolder ) {
3074                                 num_of_processors++
3075                         }
3076                         
3077                         i = 0
3078                         ## count unique physical cpus ##
3079                         for ( i in cpu_id ) {
3080                                 cpuHolder[cpu_id[i]] = 1
3081                         }
3082                         for ( i in cpuHolder ) {                                
3083                                 num_of_cpus++
3084                         }
3085                         
3086                         i = 0           
3087                         ## count unique cores ##
3088                         for ( i in core_id ) {
3089                                 coreHolder[core_id[i]] = 1
3090                         }
3091                         for ( i in coreHolder ) {                               
3092                                 num_of_cores++
3093                         }
3094                         # final check, override the num of cores value if it clearly is wrong
3095                         # and use the raw core count and synthesize the total instead of real count
3096                         if ( ( num_of_cores == 1 ) && ( cpu_core_count * num_of_cpus > 1 ) ) {
3097                                 num_of_cores = cpu_core_count * num_of_cpus
3098                         }
3099                         
3100                         ####################################################################
3101                         #                               algorithm
3102                         # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT)
3103                         # if > 1 processor && processor id (physical id) != core id then Multi-Core Processors (MCP)
3104                         # if > 1 processor && processor ids (physical id) > 1 then Multiple Processors (SMP)
3105                         # if = 1 processor then single core/processor Uni-Processor (UP)
3106                         if ( num_of_processors > 1 )
3107                         {
3108                                 # non-multicore HT
3109                                 if ( num_of_processors == (num_of_cores * 2))
3110                                 {
3111                                         type = type "HT-"
3112                                 }
3113                                 # non-HT multi-core or HT multi-core
3114                                 if (( num_of_processors == num_of_cores) ||
3115                                         ( num_of_cpus < num_of_cores))
3116                                 {
3117                                         type = type "MCP-"
3118                                 }
3119                                 # >1 cpu sockets active
3120                                 if ( num_of_cpus > 1 )
3121                                 {
3122                                         type = type "SMP-"
3123                                 }
3124                         } else {
3125                                 type = type "UP-"
3126                         }                       
3127                         
3128                         print type " " num_of_cpus " " num_of_cores
3129                 }
3130                 ' $FILE_CPUINFO 
3131                 ) )
3132         fi
3133         temp_array=${A_CPU_TYPE_PCNT_CCNT[@]}
3134         log_function_data "A_CPU_TYPE_PCNT_CCNT: $temp_array"
3135         eval $LOGFE
3136 }
3137
3138 # Detect desktop environment in use, initial rough logic from: compiz-check
3139 # http://forlong.blogage.de/entries/pages/Compiz-Check
3140 get_desktop_environment()
3141 {
3142         eval $LOGFS
3143         
3144         # set the default, this function only runs in X, if null, don't print data out
3145         local desktop_environment='' xprop_root='' ps_aux='' 
3146         local version='' version_data='' toolkit=''
3147         
3148         # note, GNOME_DESKTOP_SESSION_ID is deprecated so we'll see how that works out
3149         # https://bugzilla.gnome.org/show_bug.cgi?id=542880
3150         if [[ -n $GNOME_DESKTOP_SESSION_ID ]]; then
3151                 version=$( get_de_app_version 'gnome-about' 'gnome' '3' )
3152                 if [[ $B_EXTRA_DATA == 'true' ]];then
3153                         # this is a hack, and has to be changed with every toolkit version change
3154                         toolkit=$( pkg-config --modversion gtk+-3.0 2>/dev/null )
3155                         if [[ -z $toolkit ]];then
3156                                 toolkit=$( pkg-config --modversion gtk+-2.0 2>/dev/null )
3157                         fi
3158                         if [[ -n $toolkit ]];then
3159                                 version="$version (Gtk $toolkit)"
3160                         fi
3161                 fi
3162                 desktop_environment="Gnome"
3163         # assume 5 will id the same, why not, no need to update in future
3164         elif [[ $KDE_SESSION_VERSION == '5' ]]; then
3165                 version_data=$( kded5 --version 2>/dev/null )
3166                 version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
3167                 if [[ -z $version ]];then
3168                         version='5'
3169                 fi
3170                 if [[ $B_EXTRA_DATA == 'true' ]];then
3171                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3172                         if [[ -n $toolkit ]];then
3173                                 version="$version (Qt $toolkit)"
3174                         fi
3175                 fi
3176                 desktop_environment="KDE"
3177         elif [[ $KDE_SESSION_VERSION == '4' ]]; then
3178                 version_data=$( kded4 --version 2>/dev/null )
3179                 version=$( grep -si '^KDE Development Platform:' <<< "$version_data" | gawk '{print $4}' )
3180                 if [[ -z $version ]];then
3181                         version='4'
3182                 fi
3183                 if [[ $B_EXTRA_DATA == 'true' ]];then
3184                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3185                         if [[ -n $toolkit ]];then
3186                                 version="$version (Qt $toolkit)"
3187                         fi
3188                 fi
3189                 desktop_environment="KDE"
3190         # KDE_FULL_SESSION property is only available since KDE 3.5.5.
3191         # src: http://humanreadable.nfshost.com/files/startkde
3192         elif [[ $KDE_FULL_SESSION == 'true' ]]; then
3193                 version_data=$( kded --version 2>/dev/null )
3194                 version=$( grep -si '^KDE:' <<< "$version_data" | gawk '{print $2}' )
3195                 # version=$( get_de_app_version 'kded' '^KDE:' '2' )
3196                 if [[ -z $version ]];then
3197                         version='3.5'
3198                 fi
3199                 if [[ $B_EXTRA_DATA == 'true' ]];then
3200                         toolkit=$( grep -si '^Qt:' <<< "$version_data" | gawk '{print $2}' )
3201                         if [[ -n $toolkit ]];then
3202                                 version="$version (Qt $toolkit)"
3203                         fi
3204                 fi
3205                 desktop_environment="KDE"
3206         # now that the primary ones have been handled, next is to find the ones with unique
3207         # xprop detections possible
3208         else
3209                 ps_aux="$( ps aux )"
3210                 if [[ -n $( type -p xprop ) ]];then
3211                         xprop_root="$( xprop -root 2>/dev/null )"
3212                         # String: "This is xfdesktop version 4.2.12"
3213                         if [[ -n $( grep -Eis '\"xfce4\"' <<< "$xprop_root" ) ]];then
3214                                 version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
3215                                 if [[ -z $version ]];then
3216                                         version='4'
3217                                 fi
3218                                 if [[ $B_EXTRA_DATA == 'true' ]];then
3219                                         toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
3220                                         if [[ -n $toolkit ]];then
3221                                                 version="$version (Gtk $toolkit)"
3222                                         fi
3223                                 fi
3224                                 desktop_environment="Xfce"
3225                         # when 5 is released, the string may need updating
3226                         elif [[ -n $( grep -is '\"xfce5\"' <<< "$xprop_root" ) ]];then
3227                                 version=$( get_de_app_version 'xfdesktop' 'xfdesktop[[:space:]]version' '5' )
3228                                 if [[ -z $version ]];then
3229                                         version='5'
3230                                 fi
3231                                 if [[ $B_EXTRA_DATA == 'true' ]];then
3232                                         toolkit=$( get_de_app_version 'xfdesktop' 'Built[[:space:]]with[[:space:]]GTK' '4' )
3233                                         if [[ -n $toolkit ]];then
3234                                                 version="$version (Gtk $toolkit)"
3235                                         fi
3236                                 fi
3237                                 desktop_environment="Xfce"
3238                         elif [[ -n $( grep -is 'BLACKBOX_PID' <<< "$xprop_root" ) ]];then
3239                                 if [[ -n $( grep -is 'fluxbox' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3240                                         version=$( get_de_app_version 'fluxbox' '^fluxbox' '2' )
3241                                         desktop_environment='Fluxbox'
3242                                 else
3243                                         desktop_environment='Blackbox'
3244                                 fi
3245                         elif [[ -n $( grep -is 'OPENBOX_PID' <<< "$xprop_root" ) ]];then
3246                                 version=$( get_de_app_version 'openbox' '^openbox' '2' )
3247                                 if [[ -n $( grep -is 'lxde' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3248                                         if [[ -n $version ]];then
3249                                                 version="(Openbox $version)"
3250                                         fi
3251                                         desktop_environment='LXDE'
3252                                 else
3253                                         desktop_environment='Openbox'
3254                                 fi
3255                         elif [[ -n $( grep -is 'ICEWM' <<< "$xprop_root" ) ]];then
3256                                 version=$( get_de_app_version 'icewm' '^icewm' '2' )
3257                                 desktop_environment='IceWM'
3258                         elif [[ -n $( grep -is 'ENLIGHTENMENT' <<< "$xprop_root" ) ]];then
3259                                 # no -v or --version but version is in xprop -root
3260                                 # ENLIGHTENMENT_VERSION(STRING) = "Enlightenment 0.16.999.49898"
3261                                 version=$( grep -is 'ENLIGHTENMENT_VERSION' <<< "$xprop_root" | cut -d '"' -f 2 | gawk '{print $2}' )
3262                                 desktop_environment='Enlightenment'
3263                         fi
3264                 fi
3265                 # a few manual hacks for things that don't id with xprop, these are just good guesses
3266                 # note that gawk is going to exit after first occurance of search string, so no need for extra
3267                 if [[ -z $desktop_environment ]];then
3268                         if [[ -n $( grep -is 'fvwm-crystal'  <<< "$ps_aux" | grep -v 'grep' ) ]];then
3269                                 version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
3270                                 desktop_environment='FVWM-Crystal'
3271                         elif [[ -n $( grep -is 'fvwm'  <<< "$ps_aux" | grep -v 'grep' ) ]];then
3272                                 version=$( get_de_app_version 'fvwm' '^fvwm' '2' )
3273                                 desktop_environment='FVWM'
3274                         elif [[ -n $( grep -is 'pekwm'  <<< "$ps_aux" | grep -v 'grep' ) ]];then
3275                                 version=$( get_de_app_version 'pekwm' '^pekwm' '3' )
3276                                 desktop_environment='pekwm'
3277                         elif [[ -n $( grep -is 'awesome' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3278                                 version=$( get_de_app_version 'awesome' '^awesome' '2' )
3279                                 desktop_environment='Awesome'
3280                         elif [[ -n $( grep -is 'scrotwm' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3281                                 version=$( get_de_app_version 'scrotwm' '^welcome.*scrotwm' '4' )
3282                                 desktop_environment='Scrotwm' # no --version for this one
3283                         elif [[ -n $( grep -Eis '([[:space:]]|/)twm' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3284                                 desktop_environment='Twm' # no --version for this one
3285                         elif [[ -n $( grep -Eis '([[:space:]]|/)dwm' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3286                                 version=$( get_de_app_version 'dwm' '^dwm' '1' )
3287                                 desktop_environment='dwm'
3288                         elif [[ -n $( grep -is 'wmii' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3289                                 version=$( get_de_app_version 'wmii' '^wmii' '1' )
3290                                 desktop_environment='wmii'
3291                         elif [[ -n $( grep -Eis '([[:space:]]|/)jwm' <<< "$ps_aux" | grep -v 'grep' ) ]];then
3292                                 version=$( get_de_app_version 'jwm' '^jwm' '2' )
3293                                 desktop_environment='JWM'
3294                         fi
3295                 fi
3296         fi
3297         if [[ -n $version ]];then
3298                 version=" $version"
3299         fi
3300         echo "$desktop_environment${version}"
3301         eval $LOGFE
3302 }
3303
3304 # note: gawk doesn't support white spaces in search string, gave errors, so use [[:space:]] instead
3305 # args: $1 - desktop command for --version; $2 - search string; $3 - gawk print number
3306 get_de_app_version()
3307 {
3308         local version_data='' version='' get_version='--version' 
3309         
3310         case $1 in
3311                 dwm|jwm|wmii)
3312                         get_version='-v'
3313                         ;;
3314         esac
3315         # note, some wm send version info to stderr instead of stdout
3316         case $1 in
3317                 dwm|scrotwm)
3318                         version_data="$( $1 $get_version 2>&1 )"
3319                         ;;
3320                 *)
3321                         version_data="$( $1 $get_version 2>/dev/null )"
3322                         ;;
3323         esac
3324         
3325         if [[ -n $version_data ]];then
3326                 version=$( gawk '
3327                 BEGIN {
3328                         IGNORECASE=1
3329                 }
3330                 /'$2'/ {
3331                         # sample: dwm-5.8.2, Â©.. etc, why no space? who knows. Also get rid of v in number string
3332                         # xfce, and other, output has , in it, so dump all commas
3333                         gsub(/(,|dwm-|wmii-|v|V)/, "",$'$3') 
3334                         print $'$3'
3335                         exit # quit after first match prints
3336                 }' <<< "$version_data" )
3337         fi
3338         echo $version
3339 }
3340
3341 # for more on distro id, please reference this python thread: http://bugs.python.org/issue1322
3342 ## return distro name/id if found
3343 get_distro_data()
3344 {
3345         eval $LOGFS
3346         local i='' j='' distro='' distro_file='' a_distro_glob=''
3347
3348         # get the wild carded array of release/version /etc files if present
3349         shopt -s nullglob
3350         cd /etc
3351         a_distro_glob=(*[-_]{release,version})
3352         cd "$OLDPWD"
3353         shopt -u nullglob
3354
3355         if [[ ${#a_distro_glob[@]} -eq 1 ]];then
3356                 distro_file="${a_distro_glob}"
3357         # use the file if it's in the known good lists
3358         elif [[ ${#a_distro_glob[@]} -gt 1 ]];then
3359                 for i in $DISTROS_DERIVED $DISTROS_PRIMARY
3360                 do
3361                         # Only echo works with ${var[@]}, not print_screen_output() or script_debugger()
3362                         # This is a known bug, search for the word "strange" inside comments
3363                         # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'"
3364                         if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then
3365                                 # Now lets see if the distro file is in the known-good working-lsb-list
3366                                 # if so, use lsb-release, if not, then just use the found file
3367                                 # this is for only those distro's with self named release/version files
3368                                 # because Mint does not use such, it must be done as below
3369                                 ## this if statement requires the spaces and * as it is, else it won't work
3370                                 ##
3371                                 if [[ " $DISTROS_LSB_GOOD " == *" ${i} "* ]] && [[ $B_LSB_FILE == 'true' ]];then
3372                                         distro_file='lsb-release'
3373                                 else
3374                                         distro_file="${i}"
3375                                 fi
3376                                 break
3377                         fi
3378                 done
3379         fi
3380         log_function_data "distro_file: $distro_file"
3381         # first test for the legacy antiX distro id file
3382         if [[ -e /etc/antiX ]];then
3383                 distro="$( grep -Eoi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )"
3384         # this handles case where only one release/version file was found, and it's lsb-release. This would
3385         # never apply for ubuntu or debian, which will filter down to the following conditions. In general
3386         # if there's a specific distro release file available, that's to be preferred, but this is a good backup.
3387         elif [[ -n $distro_file && -f $FILE_LSB_RELEASE && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then
3388                 distro=$( get_distro_lsb_data )
3389         elif [[ $distro_file == 'lsb-release' ]];then
3390                 distro=$( get_distro_lsb_data )
3391         # then if the distro id file was found and it's not in the exluded primary distro file list, read it
3392         elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then
3393                 distro=$( remove_erroneous_chars "/etc/$distro_file" )
3394         # otherwise try  the default debian/ubuntu /etc/issue file
3395         elif [[ -f /etc/issue ]];then
3396                 # lsb gives more manageable and accurate output than issue, but mint should use issue for now
3397                 # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]]
3398                 if [[ $B_LSB_FILE == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then
3399                         distro=$( get_distro_lsb_data )
3400                 else
3401                         distro=$( gawk '
3402                         BEGIN {
3403                                 RS=""
3404                         }
3405                         {
3406                                 gsub(/\\[a-z]/, "")
3407                                 gsub(/,/, " ")
3408                                 gsub(/^ +| +$/, "")
3409                                 gsub(/ [ \t]+/, " ")
3410                                 print
3411                         }' /etc/issue )
3412                 fi
3413         fi
3414
3415         if [[ ${#distro} -gt 80 ]] &&  [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then
3416                 distro="${RED}/etc/${distro_file} corrupted, use -% to override${NORMAL}"
3417         fi
3418         ## note: would like to actually understand the method even if it's not used
3419         # : ${distro:=Unknown distro o_O}
3420         ## test for /etc/lsb-release as a backup in case of failure, in cases where > one version/release file
3421         ## were found but the above resulted in null distro value
3422         if [[ -z $distro ]] && [[ $B_LSB_FILE == 'true' ]];then
3423                 distro=$( get_distro_lsb_data )
3424         fi
3425         # now some final null tries
3426         if [[ -z $distro ]];then
3427                 # if the file was null but present, which can happen in some cases, then use the file name itself to 
3428                 # set the distro value. Why say unknown if we have a pretty good idea, after all?
3429                 if [[ -n $distro_file ]] && [[ " $DISTROS_DERIVED $DISTROS_PRIMARY " == *" $distro_file "* ]];then
3430                         distro=$( sed -E -e 's/[-_]//' -e 's/(release|version)//' <<< $distro_file | sed -E 's/^([a-z])/\u\1/' )
3431                 fi
3432                 ## finally, if all else has failed, give up
3433                 if [[ -z $distro ]];then
3434                         distro='unknown'
3435                 fi
3436         fi
3437
3438         # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted
3439         if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then
3440                 distro='Arch Linux'
3441         fi
3442
3443         echo "$distro"
3444         log_function_data "distro: $distro"
3445         eval $LOGFE
3446 }
3447
3448 # args: $1 - optional, app, uses the app test, not being used now
3449 get_distro_lsb_data()
3450 {
3451         eval $LOGFS
3452         local distro=''
3453
3454         if [[ $B_LSB_FILE == 'true' ]] && [[ $1 != 'app' ]];then
3455                 distro=$( gawk -F '=' '
3456                 BEGIN {
3457                         IGNORECASE=1
3458                 }
3459                 # note: adding the spacing directly to variable to make sure distro output is null if not found
3460                 /^DISTRIB_ID/ {
3461                         gsub(/^ +| +$/, "", $NF)
3462                         # this is needed because grep for "arch" is too loose to be safe
3463                         if ( $NF == "arch" ) {
3464                                 distroId = "Arch Linux"
3465                         }
3466                         else if ( $NF != "n/a" ) {
3467                                 distroId = $NF " "
3468                         }
3469                 }
3470                 /^DISTRIB_RELEASE/ {
3471                         gsub(/^ +| +$/, "", $NF)
3472                         if ( $NF != "n/a" ) {
3473                                 distroRelease = $NF " "
3474                         }
3475                 }
3476                 /^DISTRIB_CODENAME/ {
3477                         gsub(/^ +| +$/, "", $NF)
3478                         if ( $NF != "n/a" ) {
3479                                 distroCodename = $NF " "
3480                         }
3481                 }
3482                 # sometimes some distros cannot do their lsb-release files correctly, so here is
3483                 # one last chance to get it right.
3484                 /^DISTRIB_DESCRIPTION/ {
3485                         gsub(/^ +| +$/, "", $0)
3486                         if ( $NF != "n/a" ) {
3487                                 # slice out the part inside "", like: DISTRIB_DESCRIPTION="Arch Linux"
3488                                 gsub(/DISTRIB_DESCRIPTION=|"/,"",$0)
3489                                 distroDescription = $0
3490                         }
3491                 }
3492                 END {
3493                         fullString=""
3494                         if ( distroId == "" && distroRelease == "" && distroCodename == "" && distroDescription != "" ){
3495                                 fullString = distroDescription
3496                         }
3497                         else {
3498                                 fullString = distroId distroRelease distroCodename
3499                         }
3500                         print fullString
3501                 }
3502                 ' $FILE_LSB_RELEASE )
3503                 log_function_data 'cat' "$FILE_LSB_RELEASE"
3504         fi
3505         # this is HORRIBLY slow, but I don't know why, it runs fast in shell
3506 #       if [[  -n $( type -p lsb_release ) && $1 == 'app' ]];then
3507 #               distro=$( echo "$( lsb_release -irc )" | gawk '
3508 #               { IGNORECASE=1 }
3509 #               /^Distributor ID/ {
3510 #                       gsub(/^ +| +$/, "", $NF)
3511 #                       distroId = $NF
3512 #               }
3513 #               /^Release/ {
3514 #                       gsub(/^ +| +$/, "", $NF)
3515 #                       distroRelease = $NF
3516 #               }
3517 #               /^Codename/ {
3518 #                       gsub(/^ +| +$/, "", $NF)
3519 #                       distroCodename = $NF
3520 #               }
3521 #               END {
3522 #                       print distroId " " distroRelease " (" distroCodename ")"
3523 #               }' )
3524 #       fi
3525
3526         echo $distro
3527         log_function_data "distro: $distro"
3528         eval $LOGFE
3529 }
3530
3531 get_gcc_kernel_version()
3532 {
3533         # note that we use gawk to get the last part because beta, alpha, git versions can be non-numeric
3534         local gccVersion=$( grep -Eio 'gcc[[:space:]]*version[[:space:]]*([^ \t]*)' /proc/version 2>/dev/null | gawk '{print $3}' )
3535         echo $gccVersion
3536 }
3537
3538 get_gcc_system_version()
3539 {
3540         eval $LOGFS
3541         local separator='' gcc_installed='' gcc_list='' gcc_others='' temp_array=''
3542         local gcc_version=$( 
3543         gcc --version 2>/dev/null | sed -E 's/\([^\)]*\)//g' | gawk '
3544         BEGIN {
3545                 IGNORECASE=1
3546         }
3547         /^gcc/ {
3548                 print $2
3549                 exit
3550         }'
3551         )
3552
3553         # can't use xargs -l basename because not all systems support thats
3554         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
3555                 gcc_others=$( ls /usr/bin/gcc-* 2>/dev/null )
3556                 if [[ -n $gcc_others ]];then
3557                         for item in $gcc_others
3558                         do
3559                                 gcc_installed=$( basename $item | gawk -F '-' '
3560                                 $2 ~ /^[0-9\.]+$/ {
3561                                         print $2
3562                                 }' )
3563                                 if [[ -n $gcc_installed && -z $( grep "^$gcc_installed" <<< $gcc_version ) ]];then
3564                                         gcc_list=$gcc_list$separator$gcc_installed
3565                                         separator=','
3566                                 fi
3567                         done
3568                 fi
3569         fi
3570         if [[ -n $gcc_version ]];then
3571                 A_GCC_VERSIONS=( "$gcc_version" $gcc_list )
3572         fi
3573         temp_array=${A_GCC_VERSIONS[@]}
3574         log_function_data "A_GCC_VERSIONS: $temp_array"
3575         eval $LOGFE
3576 }
3577 get_gpu_temp_data()
3578 {
3579         local gpu_temp='' gpu_fan='' screens='' screen_nu='' gpu_temp_looper=''
3580
3581         # we'll try for nvidia/ati, then add if more are shown
3582         if [[ -n $( type -p nvidia-settings ) ]];then
3583                 # first get the number of screens
3584                 screens=$( nvidia-settings -q screens | gawk '
3585                 /:[0-9]\.[0-9]/ {
3586                         screens=screens gensub(/(.*)(:[0-9]\.[0-9])(.*)/, "\\2", "1", $0) " "
3587                 }
3588                 END {
3589                         print screens
3590                 }
3591                 ' )
3592                 # now we'll get the gpu temp for each screen discovered. The print out function
3593                 # will handle removing screen data for single gpu systems
3594                 for screen_nu in $screens
3595                 do
3596                         gpu_temp_looper=$( nvidia-settings -c $screen_nu -q GPUCoreTemp | gawk -F ': ' '
3597                         BEGIN {
3598                                 IGNORECASE=1
3599                                 gpuTemp=""
3600                                 gpuTempWorking=""
3601                         }
3602                         /Attribute (.*)[0-9]+\.$/ {
3603                                 gsub(/\./, "", $2)
3604                                 if ( $2 ~ /^[0-9]+$/ ) {
3605                                         gpuTemp=gpuTemp $2 "C "
3606                                 }
3607                         }
3608                         END {
3609                                 print gpuTemp
3610                         }'
3611                         )
3612                         screen_nu=$( cut -d ':' -f 2 <<< $screen_nu )
3613                         gpu_temp="$gpu_temp$screen_nu:$gpu_temp_looper "
3614                 done
3615         elif [[ -n $( type -p aticonfig ) ]];then
3616 #               gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' '
3617                 gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' '
3618                 BEGIN {
3619                         IGNORECASE=1
3620                         gpuTemp=""
3621                         gpuTempWorking=""
3622                 }
3623                 /Sensor (.*)[0-9\.]+ / {
3624                         gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2)
3625                         if ( gpuTempWorking ~ /^[0-9\.]+$/ ) {
3626                                 gpuTemp=gpuTemp gpuTempWorking "C "
3627                         }
3628                 }
3629                 END {
3630                         print gpuTemp
3631                 }'
3632                 )
3633         # this handles some newer cases of free driver temp readouts, will require modifications as
3634         # more user data appears.
3635         elif [[ -n $Sensors_Data ]];then
3636                 gpu_temp=$( 
3637                 gawk '
3638                 BEGIN {
3639                         IGNORECASE=1
3640                         gpuTemp=""
3641                         separator=""
3642                 }
3643                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
3644                         while ( getline && !/^$/  ) {
3645                                 if ( /^temp/ ) {
3646                                         sub(/^[[:alnum:]]*.*:/, "", $0 ) # clear out everything to the :
3647                                         gsub(/[\+ \t°]/, "", $1) # Â° is a special case, like a space for gawk
3648                                         gpuTemp=gpuTemp separator $1
3649                                         separator=","
3650                                 }       
3651                         }
3652                 }
3653                 END {
3654                         print gpuTemp
3655                 }' <<< "$Sensors_Data"
3656                 )
3657         fi
3658         
3659         if [[ -n $gpu_temp ]];then
3660                 echo $gpu_temp
3661         fi
3662 }
3663
3664 ## for possible future data, not currently used
3665 get_graphics_agp_data()
3666 {
3667         eval $LOGFS
3668         local agp_module=''
3669
3670         if [[ $B_MODULES_FILE == 'true' ]];then
3671                 ## not used currently
3672                 agp_module=$( gawk '
3673                 /agp/ && !/agpgart/ && $3 > 0 {
3674                         print(gensub(/(.*)_agp.*/,"\\1","g",$1))
3675                 }' $FILE_MODULES )
3676                 log_function_data 'cat' "$FILE_MODULES"
3677         fi
3678         log_function_data "agp_module: $agp_module"
3679         eval $LOGFE
3680 }
3681
3682 ## create array of gfx cards installed on system
3683 get_graphics_card_data()
3684 {
3685         eval $LOGFS
3686         local i='' temp_array=''
3687
3688         IFS=$'\n'
3689         A_GFX_CARD_DATA=( $( gawk -F': ' '
3690         BEGIN {
3691                 IGNORECASE=1
3692                 busId=""
3693         }
3694         /vga compatible controller/ {
3695                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF)
3696                 gsub(/,/, " ", $NF)
3697                 gsub(/^ +| +$/, "", $NF)
3698                 gsub(/ [ \t]+/, " ", $NF)
3699                 busId=gensub(/^([0-9a-f:\.]+) (.+)$/,"\\1","",$1)
3700                 print $NF "," busId
3701         }' <<< "$Lspci_Data" ) )
3702         IFS="$ORIGINAL_IFS"
3703 #       for (( i=0; i < ${#A_GFX_CARD_DATA[@]}; i++ ))
3704 #       do
3705 #               A_GFX_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GFX_CARD_DATA[i]}" )
3706 #       done
3707
3708         # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory..
3709         # GFXMEM="size=[$(echo "$Lspci_Data" | gawk '/VGA/{while (!/^$/) {getline;if (/size=[0-9][0-9]*M/) {size2=gensub(/.*\[size=([0-9]+)M\].*/,"\\1","g",$0);if (size<size2){size=size2}}}}END{print size2}')M]"
3710         temp_array=${A_GFX_CARD_DATA[@]}
3711         log_function_data "A_GFX_CARD_DATA: $temp_array"
3712         eval $LOGFE
3713 }
3714
3715 get_graphics_driver()
3716 {
3717         eval $LOGFS
3718         
3719         # list is from sgfxi plus non-free drivers
3720         local driver_list='apm|ark|ati|chips|cirrus|cyrix|fbdev|fglrx|glint|i128|i740|intel|i810|imstt|mach64|mga|neomagic|nsc|nv|nvidia|openchrome|nouveau|radeon|radeonhd|rendition|s3|s3virge|savage|siliconmotion|sis|sisusb|tdfx|tga|trident|tseng|unichrome|vboxvideo|vesa|vga|via|voodoo|vmware|v4l'
3721         local driver='' driver_string='' xorg_log_data='' status='' temp_array=''
3722
3723         if [[ $B_XORG_LOG == 'true' ]];then
3724                 A_GRAPHIC_DRIVERS=( $(
3725                 gawk '
3726                 BEGIN {
3727                         driver=""
3728                 }
3729                 /[[:space:]]Loading.*('"$driver_list"')_drv.so$/ {
3730                         driver=gensub(/.*[[:space:]]Loading.*('"$driver_list"')_drv.so/, "\\1", 1, $0 )
3731                         # we get all the actually loaded drivers first, we will use this to compare the
3732                         # failed/unloaded, which have not always actually been truly loaded
3733                         aDrivers[driver]="loaded" 
3734                 }
3735                 /Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/ {
3736                         driver=gensub(/(.*)Unloading[[:space:]].*('"$driver_list"')(|_drv.so)$/, "\\2", 1, $0 )
3737                         # we need to make sure that the driver has already been truly loaded, not just discussed
3738                         if ( driver in aDrivers ) {
3739                                 aDrivers[driver]="unloaded"
3740                         }
3741                 }
3742                 /Failed.*('"$driver_list"')_drv.so|Failed.*\"('"$driver_list"')\"/ {
3743                         driver=gensub(/(.*)Failed.*('"$driver_list"')_drv.so/, "\\2", 1, $0 )
3744                         if ( driver == $0 ) {
3745                                 driver=gensub(/(.*)Failed.*\"('"$driver_list"')\".*|fred/, "\\2", 1, $0 )
3746                         }
3747                         # we need to make sure that the driver has already been truly loaded, not just discussed
3748                         if ( driver != $0 && driver in aDrivers ) {
3749                                 aDrivers[driver]="failed"
3750                         }
3751                 }
3752                 END {
3753                         for ( driver in aDrivers ) {
3754                                 print driver "," aDrivers[driver]
3755                         }
3756                 }' < $FILE_XORG_LOG
3757                 ) )
3758         fi
3759         temp_array=${A_GRAPHIC_DRIVERS[@]}
3760         log_function_data "A_GRAPHIC_DRIVERS: $temp_array"
3761         
3762         eval $LOGFE
3763 }
3764
3765 ## create array of glx data
3766 get_graphics_glx_data()
3767 {
3768         eval $LOGFS
3769         local temp_array=''
3770         if [[ $B_SHOW_X_DATA == 'true' && $B_ROOT != 'true' ]];then
3771                 IFS=$'\n'
3772                 A_GLX_DATA=( $( glxinfo | gawk -F ': ' '
3773                 # note: function declarations go before BEGIN? It appears so, confirm.
3774                 # the real question here though is why this function is even here, seems
3775                 # just to be a complicated way to pack/print a variable, but maybe the
3776                 # original idea was to handle > 1 cases of detections I guess
3777                 function join( arr, sep ) {
3778                         s=""
3779                         i=flag=0
3780                         for ( i in arr ) {
3781                                 if ( flag++ ) {
3782                                         s = s sep
3783                                 }
3784                                 s = s i
3785                         }
3786                         return s
3787                 }
3788
3789                 BEGIN {
3790                         IGNORECASE=1
3791                 }
3792                 /opengl renderer/ {
3793                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $2)
3794                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
3795                         gsub(/^ +| +$/, "", $2)
3796                         if ( $2 ~ /mesa/ ) {
3797                                 # Allow all mesas
3798 #                               if ( $2 ~ / r[3-9][0-9][0-9] / ) {
3799                                         a[$2]
3800                                         # this counter failed in one case, a bug, and is not needed now
3801 #                                       f++
3802 #                               }
3803                                 next
3804                         }
3805                         
3806                         $2 && a[$2]
3807                 }
3808                 # dropping all conditions from this test to just show full mesa information
3809                 # there is a user case where not f and mesa apply, atom mobo
3810                 # /opengl version/ && ( f || $2 !~ /mesa/ ) {
3811                 /opengl version/ {
3812                         # fglrx started appearing with this extra string, does not appear to communicate anything of value
3813                         sub(/Compatibility Profile Context/, "- CPC", $2 )
3814                         gsub(/ [ \t]+/, " ", $2) # get rid of the created white spaces
3815                         gsub(/^ +| +$/, "", $2)
3816                         $2 && b[$2]
3817                 }
3818                 /direct rendering/ {
3819                         $2 && c[$2]
3820                 }
3821                 END {
3822                         printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) )
3823                 }' ) )
3824                 IFS="$ORIGINAL_IFS"
3825
3826                 # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
3827                 #    GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}')
3828         fi
3829         temp_array=${A_GLX_DATA[@]}
3830         log_function_data "A_GLX_DATA: $temp_array"
3831         eval $LOGFE
3832 }
3833
3834 ## return screen resolution / tty resolution
3835 get_graphics_res_data()
3836 {
3837         eval $LOGFS
3838         local screen_resolution='' xdpy_data='' screens_count=0
3839
3840         if [[ $B_SHOW_X_DATA == 'true' && $B_ROOT != 'true' ]];then
3841                 # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in
3842                 # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0
3843                 xdpy_data="$( xdpyinfo )"
3844                 xdpy_count=$( grep -c 'dimensions' <<< "$xdpy_data" )
3845                 # we get a bit more info from xrandr than xdpyinfo, but xrandr fails to handle
3846                 # multiple screens from different video cards
3847                 if [[ $xdpy_count -eq 1 ]];then
3848                         screen_resolution=$( xrandr | gawk '
3849                         /\*/ {
3850                                 res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0)
3851                         }
3852                         END {
3853                                 for (n in res) {
3854                                         if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) {
3855                                                 line = line ? line ", " res[n] : res[n]
3856                                         }
3857                                 }
3858                                 if (line) {
3859                                         print(line)
3860                                 }
3861                         }' )
3862                 fi
3863                 if [[ -z $screen_resolution || $xdpy_count -gt 1 ]];then
3864                         screen_resolution=$( gawk '
3865                         BEGIN {
3866                                 IGNORECASE=1
3867                                 screens = ""
3868                                 separator = ""
3869                         }
3870                         /dimensions/ {
3871                                 screens = screens separator # first time, this is null, next, has comma last
3872                                 screens = screens $2 # then tack on the new value for nice comma list
3873                                 separator = ", "
3874                         }
3875                         END {
3876                                 print screens
3877                         }' <<< "$xdpy_data" )
3878                 fi
3879         else
3880                 screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{
3881                         print $2"x"$1
3882                 }' )
3883         fi
3884         echo "$screen_resolution"
3885         log_function_data "screen_resolution: $screen_resolution"
3886         eval $LOGFE
3887 }
3888
3889 ## create array of x vendor/version data
3890 get_graphics_x_data()
3891 {
3892         eval $LOGFS
3893         local x_vendor='' x_version='' temp_array='' xdpy_info='' a_x_working=''
3894
3895         if [[ $B_SHOW_X_DATA == 'true' && $B_ROOT != 'true' ]];then
3896                 # X vendor and version detection.
3897                 # new method added since radeon and X.org and the disappearance of <X server name> version : ...etc
3898                 # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2
3899                 # A failover mechanism is in place. (if $x_version is empty, the release number is parsed instead)
3900                 # xdpy_info="$( xdpyinfo )"
3901                 IFS=","
3902                 a_x_working=( $( xdpyinfo | gawk -F': +' '
3903                 BEGIN {
3904                         IGNORECASE=1
3905                         vendorString=""
3906                         version=""
3907                         vendorRelease=""
3908                 }
3909                 /vendor string/ {
3910                         gsub(/the|inc|foundation|project|corporation/, "", $2)
3911                         gsub(/,/, " ", $2)
3912                         gsub(/^ +| +$/, "", $2)
3913                         gsub(/ [ \t]+/, " ", $2)
3914                         vendorString = $2
3915                 }
3916                 /version:/ {
3917                         version = $NF
3918                 }
3919                 /vendor release number/ {
3920                         gsub(/0+$/, "", $2)
3921                         gsub(/0+/, ".", $2)
3922                         vendorRelease = $2
3923                 }
3924                 END {
3925                         print vendorString "," version "," vendorRelease
3926                 }' ) )
3927                 x_vendor=${a_x_working[0]}
3928                 x_version=${a_x_working[1]}
3929
3930                 # this gives better output than the failure last case, which would only show:
3931                 # for example: X.org: 1.9 instead of: X.org: 1.9.0
3932                 if [[ -z $x_version ]];then
3933                         x_version=$( get_graphics_x_version )
3934                 fi
3935                 if [[ -z $x_version ]];then
3936                         x_version=${a_x_working[2]}
3937                 fi
3938                 
3939                 # some distros, like fedora, report themselves as the xorg vendor, so quick check
3940                 # here to make sure the vendor string includes Xorg in string
3941                 if [[ -z $( grep -E '(X|xorg|x\.org)' <<< $x_vendor ) ]];then
3942                         x_vendor="$x_vendor X.org"
3943                 fi
3944                 IFS="$ORIGINAL_IFS"
3945                 A_X_DATA[0]="$x_vendor"
3946                 A_X_DATA[1]="$x_version"
3947         else
3948                 x_version=$( get_graphics_x_version )
3949                 if [[ -n $x_version ]];then
3950                         x_vendor='X.org'
3951                         A_X_DATA[0]="$x_vendor"
3952                         A_X_DATA[1]="$x_version"
3953                 fi
3954         fi
3955         temp_array=${A_X_DATA[@]}
3956         log_function_data "A_X_DATA: $temp_array"
3957         eval $LOGFE
3958 }
3959
3960 # if other tests fail, try this one, this works for root, out of X also
3961 get_graphics_x_version()
3962 {
3963         eval $LOGFS
3964         local x_version='' x_data=''
3965         # note that some users can have /usr/bin/Xorg but not /usr/bin/X
3966         if [[ -n $( type -p X ) ]];then
3967                 # note: MUST be this syntax: X -version 2>&1
3968                 # otherwise X -version overrides everything and this comes out null.
3969                 # two knowns id strings: X.Org X Server 1.7.5 AND X Window System Version 1.7.5
3970                 #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }'
3971                 x_data="$( X -version 2>&1 )"
3972         elif [[ -n $( type -p Xorg ) ]];then
3973                 x_data="$( Xorg -version 2>&1)"
3974         fi
3975         if [[ -n $x_data ]];then
3976                 x_version=$( 
3977                 gawk '
3978                 BEGIN {
3979                         IGNORECASE=1
3980                 }
3981                 /^x.org x server/ {
3982                         print $4
3983                         exit
3984                 }
3985                 /^X Window System Version/ {
3986                         print $5
3987                         exit
3988                 }' <<< "$x_data"
3989                 )
3990         fi
3991         echo $x_version
3992         log_function_data " x_version: $x_version"
3993         eval $LOGFE
3994 }
3995
3996 # this gets just the raw data, total space/percent used and disk/name/per disk capacity
3997 get_hdd_data_basic()
3998 {
3999         eval $LOGFS
4000         local hdd_used='' temp_array=''
4001         local hdd_data="$( df -P --exclude-type=aufs --exclude-type=squashfs --exclude-type=unionfs --exclude-type=devtmpfs --exclude-type=tmpfs --exclude-type=iso9660 )"
4002         log_function_data 'raw' "hdd_data:\n$hdd_data"
4003         
4004         hdd_used=$( echo "$hdd_data" | gawk '
4005         # also handles odd dm-1 type, from lvm
4006         /^\/dev\/(mapper\/|[hsv]d[a-z][0-9]+|dm[-]?[0-9]+)/ {
4007                 # this handles the case where the first item is too long
4008                 # and makes df wrap output to next line, so here we advance
4009                 # it to the next line for that single case. Using df -P should
4010                 # make this unneeded but leave it in just in case
4011                 if ( NF < 5 && $0 !~ /.*%/ ) {
4012                         getline
4013                 }
4014                 # if the first item caused a wrap, use one less than standard
4015                 # testing for the field with % in it, ie: 34%, then go down from there
4016                 # this also protects against cases where the mount point has a space in the
4017                 # file name, thus breaking going down from $NF directly.
4018                 if ( $4 ~ /.*%/ ) {
4019                         used += $2
4020                 }
4021                 # otherwise use standard
4022                 else if ( $5 ~ /.*%/ ) {
4023                         used += $3
4024                 }
4025                 # and if this is not detected, give up, we need user data to debug
4026                 else {
4027                         next
4028                 }
4029         }
4030         END {
4031                 print used
4032         }' )
4033
4034         if [[ -z $hdd_used ]];then
4035                 hdd_used='na'
4036         fi
4037         log_function_data "hdd_used: $hdd_used"
4038         # create the initial array strings:
4039         # disk-dev, capacity, name, usb or not
4040         # final item is the total of the disk
4041         IFS=$'\n'
4042
4043         if [[ $B_PARTITIONS_FILE == 'true' ]];then
4044                 A_HDD_DATA=( $(
4045                 gawk -v hddused="$hdd_used" '
4046                 /[hsv]d[a-z]$/ {
4047                         driveSize = $(NF - 1)*1024/1000**3
4048                         gsub(/,/, " ", driveSize)
4049                         gsub(/^ +| +$/, "", driveSize)
4050                         printf( $NF",%.1fGB,,\n", driveSize )
4051                 }
4052                 # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below
4053                 # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0  {
4054                 #       size += $3
4055                 # }
4056                 # special case from this data: 8     0  156290904 sda
4057                 $1 ~ /^(3|22|33|8)$/ && $NF ~ /[hsv]d[a-z]$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) {
4058                         size += $3
4059                 }
4060
4061                 END {
4062                         size = size*1024/1000**3                   # calculate size in GB size
4063                         workingUsed = hddused*1024/1000**3         # calculate workingUsed in GB used
4064                         # this handles a special case with livecds where no hdd_used is detected
4065                         if ( size > 0 && hddused == "na" ) {
4066                                 size = sprintf( "%.1f", size )
4067                                 print size "GB,-"
4068                         }
4069                         else if ( size > 0 && workingUsed > 0 ) {
4070                                 diskUsed = workingUsed*100/size  # calculate used percentage
4071                                 diskUsed = sprintf( "%.1f", diskUsed )
4072                                 size = sprintf( "%.1f", size )
4073                                 print size "GB," diskUsed "% used"
4074                         }
4075                         else {
4076                                 print "NA,-" # print an empty array, this will be further handled in the print out function
4077                         }
4078                 }' $FILE_PARTITIONS ) )
4079                 log_function_data 'cat' "$FILE_PARTITIONS"
4080         fi
4081         IFS="$ORIGINAL_IFS"
4082         temp_array=${A_HDD_DATA[@]}
4083         log_function_data "A_HDD_DATA: $temp_array"
4084         eval $LOGFE
4085 }
4086
4087 ## fills out the A_HDD_DATA array with disk names
4088 get_hard_drive_data_advanced()
4089 {
4090         eval $LOGFS
4091         local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j=''
4092         local sd_ls_by_id='' ls_disk_by_id='' usb_exists='' temp_array=''
4093
4094         ## check for all ide type drives, non libata, only do it if hdx is in array
4095         ## this is now being updated for new /sys type paths, this may handle that ok too
4096         if [[ -n $( grep -E 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
4097                 # remember, we're using the last array item to store the total size of disks
4098                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
4099                 do
4100                         IFS=","
4101                         a_temp_working=( ${A_HDD_DATA[i]} )
4102                         IFS="$ORIGINAL_IFS"
4103                         if [[ -n $( grep -E '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];then
4104                                 if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then
4105                                         a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )"
4106                                 else
4107                                         a_temp_working[2]="Name n/a"
4108                                 fi
4109                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
4110                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
4111                                 do
4112                                         if [[ $j -gt 0 ]];then
4113                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
4114                                         else
4115                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
4116                                         fi
4117                                 done
4118                         fi
4119                 done
4120         fi
4121
4122         ## then handle libata names
4123         # first get the ata device names, put them into an array
4124         IFS=$'\n'
4125         if [[ $B_SCSI_FILE == 'true' ]]; then
4126                 a_temp_scsi=( $( gawk  '
4127                 BEGIN {
4128                         IGNORECASE=1
4129                 }
4130                 /host/ {
4131                         getline a[$0]
4132                         getline b[$0]
4133                 }
4134                 END {
4135                         for (i in a) {
4136                                 if (b[i] ~ / *type: *direct-access.*/) {
4137                                         #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i])
4138                                         #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] )
4139                                         # the vendor: string is useless, and is a bug, ATA is not a vendor for example
4140                                         c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] )
4141                                         gsub(/,/, " ", c)
4142                                         gsub(/^ +| +$/, "", c)
4143                                         gsub(/ [ \t]+/, " ", c)
4144                                         #print a[i]
4145                                         # we actually want this data, so leaving this off for now
4146 #                                       if (c ~ /\<flash\>|\<pendrive\>|memory stick|memory card/) {
4147 #                                               continue
4148 #                                       }
4149                                         print c
4150                                 }
4151                         }
4152                 }' $FILE_SCSI ) )
4153                 log_function_data 'cat' "$FILE_SCSI"
4154         fi
4155         IFS="$ORIGINAL_IFS"
4156
4157         ## then we'll loop through that array looking for matches.
4158         if [[ -n $( grep -E 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then
4159                 # first pack the main ls variable so we don't have to keep using ls /dev...
4160                 ls_disk_by_id="$( ls -l /dev/disk/by-id )"
4161                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
4162                 do
4163                         if [[ -n $( grep -E '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then
4164                                 IFS=","
4165                                 a_temp_working=( ${A_HDD_DATA[$i]} )
4166                                 IFS="$ORIGINAL_IFS"
4167                                 # /sys/block/[sda,hda]/device/model
4168                                 # this is handles the new /sys data types first
4169                                 if [[ -e /sys/block/${a_temp_working[0]}/device/model ]];then
4170                                         temp_name="$( remove_erroneous_chars /sys/block/${a_temp_working[0]}/device/model )"
4171                                         temp_name=$( tr ' ' '_' <<< $temp_name | cut -d '-' -f 1 )
4172                                 elif [[ ${#a_temp_scsi[@]} -gt 0 ]];then
4173                                         for (( j=0; j < ${#a_temp_scsi[@]}; j++ ))
4174                                         do
4175                                                 ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the
4176                                                 # discovered disk name AND ends with the correct identifier, sdx
4177                                                 # get rid of whitespace for some drive names and ids, and extra data after - in name
4178                                                 temp_name=$( tr ' ' '_' <<< ${a_temp_scsi[$j]} | cut -d '-' -f 1 )
4179                                                 sd_ls_by_id=$( grep -Em1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
4180
4181                                                 if [[ -n $sd_ls_by_id ]];then
4182                                                         temp_name=${a_temp_scsi[$j]}
4183                                                         break
4184                                                 else
4185                                                         # test to see if we can get a better name output when null
4186                                                         if [[ -n $temp_name ]];then
4187                                                                 temp_name=$temp_name
4188                                                         fi
4189                                                 fi
4190                                         done
4191                                 fi
4192                                 
4193                                 if [[ -z $temp_name ]];then
4194                                         temp_name="Name n/a"
4195                                 else 
4196                                         usb_exists=$( grep -Em1 "usb-.*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" )
4197                                         if [[ -n $usb_exists ]];then
4198                                                 a_temp_working[3]='USB'
4199                                         fi
4200                                 fi
4201                                 a_temp_working[2]=$temp_name
4202                                 # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu.
4203                                 for (( j=0; j < ${#a_temp_working[@]}; j++ ))
4204                                 do
4205                                         if [[ $j -gt 0 ]];then
4206                                                 A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}"
4207                                         else
4208                                                 A_HDD_DATA[i]="${a_temp_working[$j]}"
4209                                         fi
4210                                 done
4211                         fi
4212                 done
4213                 unset ls_disk_by_id # and then let's dump the data we don't need
4214         fi
4215         temp_array=${A_HDD_DATA[@]}
4216         log_function_data "A_HDD_DATA: $temp_array"
4217         eval $LOGFE
4218 }
4219
4220 # a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers.
4221 # args: $1 - /dev/<disk> to be tested for
4222 get_hdd_temp_data()
4223 {
4224         eval $LOGFS
4225         local hdd_temp='' sudo_command='' 
4226
4227         if [[ $B_HDDTEMP_TESTED != 'true' ]];then
4228                 B_HDDTEMP_TESTED='true'
4229                 HDDTEMP_PATH=$( type -p hddtemp )
4230         fi
4231         if [[ $B_SUDO_TESTED != 'true' ]];then
4232                 B_SUDO_TESTED='true'
4233                 SUDO_PATH=$( type -p sudo )
4234         fi
4235         
4236         if [[ -n $HDDTEMP_PATH && -n $1 ]];then
4237                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
4238                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
4239                 # important: -n makes it non interactive, no prompt for password
4240                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
4241                         sudo_command='sudo -n '
4242                 fi
4243                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
4244                 hdd_temp=$( eval $sudo_command $HDDTEMP_PATH -nq -u C $1 )
4245                 if [[ -n $hdd_temp && -n $( grep -E '^([0-9\.]+)$' <<< $hdd_temp ) ]];then
4246                         echo $hdd_temp
4247                 fi
4248         fi
4249         eval $LOGFE
4250 }
4251
4252 get_lspci_data()
4253 {
4254         eval $LOGFS
4255         local lspci_data="$( lspci -v | gawk '{
4256                 gsub(/\(prog-if[^)]*\)/,"")
4257                 sub(/^0000:/, "", $0) # seen case where the 0000: is prepended, rare, but happens
4258                 print
4259         }' )"
4260         
4261         echo "$lspci_data"
4262         log_function_data 'raw' "lspci_data:\n$lspci_data"
4263         eval $LOGFE
4264 }
4265
4266 get_machine_data()
4267 {
4268         eval $LOGFS
4269         local temp_array='' separator='' id_file='' file_data='' array_string=''
4270         local id_dir='/sys/class/dmi/id/' dmi_name='' dmi_data='' 
4271         local machine_files="
4272         sys_vendor product_name product_version product_serial product_uuid 
4273         board_vendor board_name board_version board_serial 
4274         bios_vendor bios_version bios_date 
4275         "
4276         local dmi_names="
4277         system-manufacturer system-product-name system-version system-serial-number system-uuid 
4278         baseboard-manufacturer baseboard-product-name baseboard-version baseboard-serial-number 
4279         bios-vendor bios-version bios-release-date 
4280         "
4281         if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
4282                 machine_files="$machine_files
4283                 chassis_vendor chassis_type chassis_version chassis_serial
4284                 "
4285                 dmi_names="$dmi_names
4286                 chassis-manufacturer chassis-type chassis-version chassis-serial-number
4287                 "
4288         fi
4289         if [[ -d $id_dir ]];then
4290                 for id_file in $machine_files
4291                 do
4292                         file_data=''
4293                         if [[ -r $id_dir$id_file ]];then
4294                                 file_data=$( gawk '
4295                                 BEGIN {
4296                                         IGNORECASE=1
4297                                 }
4298                                 {
4299                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
4300                                         gsub(/,/, " ", $0)
4301                                         # yes, there is a typo in a user data set, unknow
4302                                         # Base Board Version|Base Board Serial Number
4303                                         # Chassis Manufacturer|Chassis Version|Chassis Serial Number
4304                                         # System manufacturer|System Product Name|System Version
4305                                         # To Be Filled By O.E.M.
4306                                         sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", $0) 
4307                                         gsub(/bios|acpi/, "", $0)
4308                                         sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
4309                                         gsub(/^ +| +$/, "", $0)
4310                                         gsub(/ [ \t]+/, " ", $0)
4311                                         print $0
4312                                 }' < $id_dir$id_file
4313                                 )
4314                         fi
4315                         array_string="$array_string$separator$file_data"
4316                         separator=','
4317                 done
4318         else
4319                 if [[ -n $( type -p dmidecode 2>/dev/null ) && -n $( dmidecode 2>/dev/null ) ]];then
4320                         if [[ $B_ROOT == 'true' ]];then
4321                                 # this handles very old systems, like Lenny 2.6.26, with dmidecode, but no data
4322                                 if [[ -z $( dmidecode 2>/dev/null | grep -i 'no smbios or dmi' ) ]];then
4323                                         array_string='dmidecode-no-smbios-dmi-data'
4324                                 else
4325                                         for dmi_name in $dmi_names
4326                                         do
4327                         #                       echo "$dmi_name" >&2
4328                                                 dmi_data=''
4329                                                 dmi_data=$( dmidecode -s $dmi_name | gawk '
4330                                                         BEGIN {
4331                                                                 IGNORECASE=1
4332                                                         }
4333                                                         {
4334                                                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
4335                                                                 gsub(/,/, " ", $0)
4336                                                                 # yes, there is a typo in a user data set, unknow
4337                                                                 # Base Board Version|Base Board Serial Number
4338                                                                 # Chassis Manufacturer|Chassis Version|Chassis Serial Number
4339                                                                 # System manufacturer|System Product Name|System Version
4340                                                                 # To Be Filled By O.E.M.
4341                                                                 sub(/^Base Board .*|^Chassis .*|.*O\.E\.M\..*|.*OEM.*|^Not .*|^System .*|.*unknow.*|.*N\/A.*|none|^To be filled.*/, "", $0) 
4342                                                                 gsub(/bios|acpi/, "", $0)
4343                                                                 sub(/http:\/\/www.abit.com.tw\//, "Abit", $0)
4344                                                                 gsub(/^ +| +$/, "", $0)
4345                                                                 gsub(/ [ \t]+/, " ", $0)
4346                                                                 print $0
4347                                                         }' )
4348                                                 array_string="$array_string$separator$dmi_data"
4349                                                 separator=','
4350                                         done
4351                                 fi
4352                         else
4353                                 array_string='dmidecode-non-root-user'
4354                         fi
4355                 fi
4356         fi
4357         IFS=','
4358         A_MACHINE_DATA=( $array_string )
4359         IFS="$ORIGINAL_IFS"
4360         temp_array=${A_MACHINE_DATA[@]}
4361         log_function_data "A_MACHINE_DATA: $temp_array"
4362         eval $LOGFE
4363 }
4364
4365 ## return memory used/installed
4366 get_memory_data()
4367 {
4368         eval $LOGFS
4369         local memory=''
4370         if [[ $B_MEMINFO_FILE == 'true' ]];then
4371                 memory=$( gawk '
4372                 /^MemTotal:/ {
4373                         tot = $2
4374                 }
4375                 /^(MemFree|Buffers|Cached):/ {
4376                         notused+=$2
4377                 }
4378                 END {
4379                         used = tot-notused
4380                         printf("%.1f/%.1fMB\n", used/1024, tot/1024)
4381                 }' $FILE_MEMINFO )
4382                 log_function_data 'cat' "$FILE_MEMINFO"
4383         fi
4384         echo "$memory"
4385         log_function_data "memory: $memory"
4386         eval $LOGFE
4387 }
4388
4389 # process and return module version data
4390 get_module_version_number()
4391 {
4392         eval $LOGFS
4393         local module_version=''
4394         
4395         if [[ $B_MODINFO_TESTED != 'true' ]];then
4396                 B_MODINFO_TESTED='true'
4397                 MODINFO_PATH=$( type -p modinfo )
4398         fi
4399
4400         if [[ -n $MODINFO_PATH ]];then
4401                 module_version=$( $MODINFO_PATH $1 2>/dev/null | gawk '
4402                 BEGIN {
4403                         IGNORECASE=1
4404                 }
4405                 /^version/ {
4406                         gsub(/,/, " ", $2)
4407                         gsub(/^ +| +$/, "", $2)
4408                         gsub(/ [ \t]+/, " ", $2)
4409                         print $2
4410                 }
4411                 ' )
4412         fi
4413
4414         echo "$module_version"
4415         log_function_data "module_version: $module_version"
4416         eval $LOGFE
4417 }
4418
4419 ## create array of network cards
4420 get_networking_data()
4421 {
4422         eval $LOGFS
4423         
4424         local B_USB_NETWORKING='false' temp_array=''
4425         
4426         IFS=$'\n'
4427         A_NETWORK_DATA=( $( 
4428         echo "$Lspci_Data" | gawk '
4429         BEGIN {
4430                 IGNORECASE=1
4431                 counter=0 # required to handle cases of > 1 instance of the same chipset
4432         }
4433         /^[0-9a-f:\.]+ (ethernet|network) (controller|bridge)/ || /^[0-9a-f:\.]+ [^:]+: .*(ethernet|network).*$/ {
4434                 nic=gensub(/^[0-9a-f:\.]+ [^:]+: (.+)$/,"\\1","g",$0)
4435                 gsub(/realtek semiconductor/, "Realtek", nic)
4436                 gsub(/davicom semiconductor/, "Davicom", nic)
4437                 # The doublequotes are necessary because of the pipes in the variable.
4438                 gsub(/'"$BAN_LIST_NORMAL"'/, "", nic)
4439                 gsub(/,/, " ", nic)
4440                 gsub(/^ +| +$/, "", nic)
4441                 gsub(/ [ \t]+/, " ", nic)
4442                 # construct a unique string ending for each chipset detected, this allows for
4443                 # multiple instances of the same exact chipsets, ie, dual gigabit 
4444                 nic = nic "~~" counter++
4445                 aPciBusId[nic] = gensub(/(^[0-9a-f:\.]+) [^:]+: .+$/,"\\1","g",$0)
4446                 # I do not understand why incrementing a string index makes sense? 
4447                 eth[nic]++ 
4448                 while ( getline && !/^$/ ) {
4449                         gsub(/,/, "", $0)
4450                         if ( /I\/O/ ) {
4451                                 ports[nic] = ports[nic] $4 " "
4452                         }
4453                         if ( /driver in use/ ) {
4454                                 drivers[nic] = drivers[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
4455                         }
4456                         else if ( /kernel modules/ ) {
4457                                 modules[nic] = modules[nic] gensub( /(.*): (.*)/ ,"\\2" ,"g" ,$0 ) ""
4458                         }
4459                 }
4460         }
4461
4462         END {
4463                 j=0
4464                 for (i in eth) {
4465                         useDrivers=""
4466                         usePorts=""
4467                         useModules=""
4468                         usePciBusId=""
4469                         if ( eth[i] > 1 ) {
4470                                 a[j] = eth[i] "x " i
4471                         }
4472                         else {
4473                                 a[j] = i
4474                         }       
4475                         ## note: this loses the plural ports case, is it needed anyway?
4476                         if ( ports[i] != "" ) {
4477                                 usePorts = ports[i]
4478                         }
4479                         if ( drivers[i] != "" ) {
4480                                 useDrivers = drivers[i]
4481                         }
4482                         if ( modules[i] != "" ) {
4483                                 useModules = modules[i]
4484                         }
4485                         if ( aPciBusId[i] != "" ) {
4486                                 usePciBusId = aPciBusId[i]
4487                         }
4488                         # create array primary item for master array
4489                         # and strip out the counter again, this handled dual cards with same chipset
4490                         sub( /~~[0-9]+$/, "", a[j] )
4491                         sub( / $/, "", usePorts ) # clean off trailing whitespace
4492                         print a[j] "," useDrivers "," usePorts "," useModules, "," usePciBusId
4493                         j++
4494                 }
4495         }'
4496         ) )
4497         IFS="$ORIGINAL_IFS"
4498         get_networking_usb_data
4499         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' || $B_USB_NETWORKING == 'true' ]];then
4500                 get_network_advanced_data
4501         fi
4502         temp_array=${A_NETWORK_DATA[@]}
4503         log_function_data "A_NETWORK_DATA: $temp_array"
4504         
4505         eval $LOGFE
4506 }
4507
4508 get_network_advanced_data()
4509 {
4510         eval $LOGFS
4511         local a_network_adv_working='' if_path='' working_path='' working_uevent_path='' dir_path=''
4512         local if_id='' speed='' duplex='' mac_id='' oper_state='' 
4513         local usb_data='' usb_vendor='' usb_product='' product_path='' driver_test=''
4514         
4515         for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
4516         do
4517                 IFS=","
4518                 a_network_adv_working=( ${A_NETWORK_DATA[i]} )
4519                 # reset these every go round
4520                 driver_test=''
4521                 if_id='' 
4522                 speed='' 
4523                 duplex='' 
4524                 mac_id='' 
4525                 oper_state=''
4526                 usb_data=''
4527                 if [[ -z $( grep '^usb-' <<< ${a_network_adv_working[4]} ) ]];then
4528                         # note although this may exist technically don't use it, it's a virtual path
4529                         # and causes weird cat errors when there's a missing file as well as a virtual path
4530                         # /sys/bus/pci/devices/0000:02:02.0/net/eth1
4531                         # real paths are: /sys/devices/pci0000:00/0000:00:1e/0/0000:02:02.0/net/eth1/uevent
4532                         # and on older debian kernels: /sys/devices/pci0000:00/0000:02:02.0/net:eth1/uevent
4533                         # but broadcom shows this sometimes:
4534                         # /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ssb0:0/uevent:['DRIVER=b43', 'MODALIAS=ssb:v4243id0812rev0D']:
4535                         working_path="/sys/bus/pci/devices/0000:${a_network_adv_working[4]}"
4536                         # now we want the real one, that xiin also displays, without symbolic links.
4537                         if [[ -e $working_path ]];then
4538                                 working_path=$( readlink -f $working_path 2>/dev/null )
4539                                 # sometimes there is another directory between the path and /net
4540                                 if [[ ! -e $working_path/net ]];then
4541                                         # using find here, probably will need to also use it in usb part since the grep
4542                                         # method seems to not be working now. Slice off the rest, which leaves the basic path
4543                                         working_path=$( find $working_path/*/net/*/uevent 2>/dev/null | \
4544                                         sed 's|/net.*||' )
4545                                 fi
4546                         fi
4547                         # working_path=$( ls /sys/devices/pci*/*/0000:${a_network_adv_working[4]}/net/*/uevent  )
4548                 else
4549                         # slice off the usb- part
4550                         usb_data=$( cut -d '-' -f 2-4 <<< ${a_network_adv_working[4]} )
4551                         usb_vendor=$( cut -d ':' -f 1 <<< $usb_data )
4552                         usb_product=$( cut -d ':' -f 2 <<< $usb_data )
4553                         # this grep returns the path plus the contents of the file, with a colon separator, so slice that off
4554                         # /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/idVendor
4555                         working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/*/idVendor | \
4556                         sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
4557                         # try an alternate path if first one doesn't work
4558                         # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/idVendor
4559                         if [[ -z $working_path ]];then
4560                                 working_path=$( grep -s "$usb_vendor" /sys/devices/pci*/*/usb*/*/idVendor | \
4561                                 sed -e "s/idVendor:$usb_vendor//"  -e '/driver/d' )
4562                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/idProduct | \
4563                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
4564                         else
4565                                 product_path=$( grep -s "$usb_product" /sys/devices/pci*/*/usb*/*/*/idProduct | \
4566                                 sed -e "s/idProduct:$usb_product//" -e '/driver/d' )
4567                         fi
4568                         
4569                         # make sure it's the right product/vendor match here, it will almost always be but let's be sure
4570                         if [[ -n $working_path && -n $product_path ]] && [[ $working_path == $product_path ]];then
4571                         #if [[ -n $working_path ]];then
4572                                 # now ls that directory and get the numeric starting sub directory and that should be the full path
4573                                 # to the /net directory part
4574                                 dir_path=$( ls ${working_path} 2>/dev/null | grep -sE '^[0-9]' )
4575                                 working_uevent_path="${working_path}${dir_path}"
4576                         fi
4577                 fi
4578                 # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/uevent grep for DRIVER=
4579                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/1-1:1.0/uevent
4580                 if [[ -n $usb_data ]];then
4581                         driver_test=$( grep -si 'DRIVER=' $working_uevent_path/uevent | cut -d '=' -f 2 )
4582                         if [[ -n $driver_test ]];then
4583                                 a_network_adv_working[1]=$driver_test
4584                         fi
4585                 fi
4586                 log_function_data "PRE: working_path: $working_path\nworking_uevent_path: $working_uevent_path"
4587                 
4588                 # this applies in two different cases, one, default, standard, two, for usb, this is actually
4589                 # the short path, minus the last longer numeric directory name, ie: 
4590                 # from debian squeeze 2.6.32-5-686: 
4591                 # /sys/devices/pci0000:00/0000:00:0b.1/usb1/1-1/net/wlan0/address
4592                 if [[ -e $working_path/net ]];then
4593                         if_path=$( ls $working_path/net 2>/dev/null )
4594                         if_id=$if_path
4595                         working_path=$working_path/net/$if_path
4596                 # this is the normal usb detection if the first one didn't work
4597                 elif [[ -n $usb_data && -e $working_uevent_path/net ]];then
4598                         if_path=$( ls $working_uevent_path/net 2>/dev/null )
4599                         if_id=$if_path
4600                         working_path=$working_uevent_path/net/$if_path
4601                 # 2.6.32 debian lenny kernel shows not: /net/eth0 but /net:eth0
4602                 else
4603                         if_path=$( ls $working_path 2>/dev/null | grep 'net:' )
4604                         if_id=$( cut -d ':' -f 2 <<< "$if_path" )
4605                         working_path=$working_path/$if_path
4606                 fi
4607                 log_function_data "POST: working_path: $working_path\nif_path: $if_path - if_id: $if_id"
4608                 
4609                 if [[ -n $if_path ]];then
4610                         if [[ -r $working_path/speed ]];then
4611                                 speed=$( cat $working_path/speed 2>/dev/null )
4612                         fi
4613                         if [[ -r $working_path/duplex ]];then
4614                                 duplex=$( cat $working_path/duplex 2>/dev/null )
4615                         fi
4616                         if [[ -r $working_path/address ]];then
4617                                 mac_id=$( cat $working_path/address 2>/dev/null )
4618                         fi
4619                         if [[ -r $working_path/operstate ]];then
4620                                 oper_state=$( cat $working_path/operstate 2>/dev/null )
4621                         fi
4622                 fi
4623                 
4624                 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
4625                 IFS="$ORIGINAL_IFS"
4626         done
4627
4628         eval $LOGFE
4629 }
4630
4631 get_networking_usb_data()
4632 {
4633         eval $LOGFS
4634         local lsusb_path='' lsusb_data='' a_usb='' array_count=''
4635         
4636         # now we'll check for usb wifi, a work in progress
4637         # USB_NETWORK_SEARCH
4638         # alsa usb detection by damentz
4639         # for every sound card symlink in /proc/asound - display information about it
4640         lsusb_path=$( type -p lsusb )
4641         # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue
4642         if [[ -n $lsusb_path ]]; then
4643                 # send error messages of lsusb to /dev/null as it will display a bunch if not a super user
4644                 lsusb_data="$( $lsusb_path 2>/dev/null )"
4645                 # also, find the contents of usbid in lsusb and print everything after the 7th word on the
4646                 # corresponding line. Finally, strip out commas as they will change the driver :)
4647                 if [[ -n $lsusb_data ]];then
4648                         IFS=$'\n'
4649                         a_usb=( $( 
4650                         gawk '
4651                         BEGIN {
4652                                 IGNORECASE=1
4653                                 string=""
4654                                 separator=""
4655                         }
4656                         /'"$USB_NETWORK_SEARCH"'/ && !/bluetooth| hub|keyboard|mouse|printer| ps2|reader|scan|storage/ {
4657                                 string=""
4658                                 gsub( /,/, " ", $0 )
4659                                 gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
4660                                 gsub(/ [ \t]+/, " ", $0)
4661                                 sub(/realtek semiconductor/, "Realtek", $0)
4662                                 sub(/davicom semiconductor/, "Davicom", $0)
4663                                 sub(/Belkin Components/, "Belkin", $0)
4664                                 for ( i=7; i<= NF; i++ ) {
4665                                         string = string separator $i
4666                                         separator = " "
4667                                 }
4668                                 if ( $6 != "" ){
4669                                         print string ",,,,usb-" $6
4670                                 }
4671                         }' <<< "$lsusb_data" 
4672                         ) )
4673                         IFS="$ORIGINAL_IFS"
4674                         if [[ ${#a_usb[@]} -gt 0 ]];then
4675                                 array_count=${#A_NETWORK_DATA[@]}
4676                                 for (( i=0; i < ${#a_usb[@]}; i++ ))
4677                                 do
4678                                         A_NETWORK_DATA[$array_count]=${a_usb[i]}
4679                                         ((array_count++))
4680                                 done
4681                                 # need this to get the driver data for -N regular output, but no need
4682                                 # to run the advanced stuff unless required
4683                                 B_USB_NETWORKING='true'
4684                         fi
4685                 fi
4686         fi
4687 #       echo $B_USB_NETWORKING
4688         eval $LOGFE
4689 }
4690
4691 get_networking_wan_ip_data()
4692 {
4693         eval $LOGFS
4694         local ip=''
4695
4696         # get ip using wget redirect to stdout. This is a clean, text only IP output url.
4697         ip=$( wget -q -O - http://smxi.org/opt/ip.php | gawk -F 'is: ' '{
4698                 #gsub("\n","",$2")
4699                 print $2
4700         }' )
4701
4702         if [[ -z $ip ]];then
4703                 ip='None Detected!'
4704         fi
4705         echo "$ip"
4706         log_function_data "ip: $ip"
4707         eval $LOGFE
4708 }
4709
4710 get_networking_local_ip_data()
4711 {
4712         eval $LOGFS
4713         
4714         local ip_tool_command=$( type -p ip )
4715         local temp_array='' ip_tool='ip' ip_tool_data=''
4716         # the chances for all new systems to have ip by default are far higher than
4717         # the deprecated ifconfig. Only try for ifconfig if ip is not present in system
4718         if [[ -z $ip_tool_command ]];then
4719                 ip_tool_command=$( type -p ifconfig )
4720                 ip_tool='ifconfig'
4721         else
4722                 ip_tool_command="$ip_tool_command addr"
4723         fi
4724         if [[ -n "$ip_tool_command" ]];then
4725                 if [[ $ip_tool == 'ifconfig' ]];then
4726                         ip_tool_data="$( $ip_tool_command )"
4727                 # note, ip addr does not have proper record separation, so creating new lines explicitly here at start
4728                 # of each IF record item. Also getting rid of the unneeded numeric line starters, now it can be parsed 
4729                 # like ifconfig more or less
4730                 elif [[ $ip_tool == 'ip' ]];then
4731                         ip_tool_data="$( eval ${ip_tool_command} | sed 's/^[0-9]\+:[[:space:]]\+/\n/' )"
4732                 fi
4733         fi
4734         if [[ -z $ip_tool_command ]];then
4735                 A_INTERFACES_DATA=( "Interfaces program 'ip' missing. Please check: $SCRIPT_NAME --recommends" )
4736         elif [[ -n "$ip_tool_data" ]];then
4737                 IFS=$'\n' # $ip_tool_command
4738                 A_INTERFACES_DATA=( $( 
4739                 gawk -v ipTool=$ip_tool '
4740                 BEGIN {
4741                         IGNORECASE=1
4742                         interface=""
4743                         ifIp=""
4744                         ifIpV6=""
4745                         ifMask=""
4746                 }
4747                 # skip past the lo item
4748                 /^lo/ {
4749                         while (getline && !/^$/ ) {
4750                                 # do nothing, just get past this entry item
4751                         }
4752                 }
4753                 /^[a-zA-Z]+[0-9]/ {
4754                         # not clear on why inet is coming through, but this gets rid of it
4755                         # as first line item.
4756                         gsub(/,/, " ", $0)
4757                         gsub(/^ +| +$/, "", $0)
4758                         gsub(/ [ \t]+/, " ", $0)
4759                         interface = $1
4760                         # prep this this for ip addr: eth0: 
4761                         sub(/:/, "", interface)
4762                         ifIp=""
4763                         ifIpV6=""
4764                         ifMask=""
4765                         aInterfaces[interface]++
4766
4767                         while (getline && !/^$/ ) {
4768                                 if ( ipTool == "ifconfig" ) {
4769                                         if (/inet addr:/) {
4770                                                 ifIp = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 )
4771                                                 if (/mask:/) {
4772                                                         ifMask = gensub( /mask:([0-9\.]+)/, "\\1", "g", $NF )
4773                                                 }
4774                                         }
4775                                         if (/inet6 addr:/) {
4776                                                 ifIpV6 = $3
4777                                         }
4778                                 }
4779                                 else if ( ipTool == "ip" ) {
4780                                         if ( $1 == "inet" ) {
4781                                                 ifIp = $2
4782                                         }
4783                                         if ( $1 == "inet6" ) {
4784                                                 ifIpV6 = $2
4785                                         }
4786                                 }
4787                         }
4788                         # slice off the digits that are sometimes tacked to the end of the address, 
4789                         # like: /64 or /24
4790                         sub(/\/[0-9]+/, "", ifIp)
4791                         sub(/\/[0-9]+/, "", ifIpV6)
4792                         ipAddresses[interface] = ifIp "," ifMask "," ifIpV6
4793                 }
4794                 END {
4795                         j=0
4796                         for (i in aInterfaces) {
4797                                 ifData = ""
4798                                 a[j] = i
4799                                 if (ipAddresses[i] != "") {
4800                                         ifData = ipAddresses[i]
4801                                 }
4802                                 # create array primary item for master array
4803                                 # tested needed to avoid bad data from above, if null it is garbage
4804                                 # this is the easiest way to handle junk I found, improve if you want
4805                                 if ( ifData != "" ) {
4806                                         print a[j] "," ifData
4807                                 }
4808                                 j++
4809                         }
4810                 }' <<< "$ip_tool_data"
4811                 ) )
4812                 IFS="$ORIGINAL_IFS"
4813         else
4814                 A_INTERFACES_DATA=( "Interfaces program $ip_tool present but created no data. " )
4815         fi
4816         temp_array=${A_INTERFACES_DATA[@]}
4817         log_function_data "A_INTERFACES_DATA: $temp_array"
4818         eval $LOGFE
4819 }
4820 # get_networking_local_ip_data;exit
4821
4822 # get_networking_local_ip_data;exit
4823 get_optical_drive_data()
4824 {
4825         eval $LOGFS
4826         
4827         local temp_array='' sys_uevent_path='' proc_cdrom='' link_list=''
4828         local separator='' linked='' disk='' item_string='' proc_info_string='' 
4829         local dev_disks_links="$( ls /dev/dvd* /dev/cd* /dev/scd* 2>/dev/null  )"
4830         # get the actual disk dev location, first try default which is easier to run, need to preserve line breaks
4831         local dev_disks_real="$( echo "$dev_disks_links" | xargs -l readlink 2>/dev/null | sort -u )"
4832         # Some systems don't support xargs -l so we need to do it manually
4833         if [[ -z $dev_disks_real ]];then
4834                 for linked in $dev_disks_links
4835                 do
4836                         disk=$( readlink $linked 2>/dev/null )
4837                         if [[ -n $disk ]];then
4838                                 disk=$( basename $disk ) # puppy shows this as /dev/sr0, not sr0
4839                                 if [[ -z $dev_disks_real || -z $( grep $disk <<< $dev_disks_real ) ]];then
4840                                         # need line break IFS for below, no white space
4841                                         dev_disks_real="$dev_disks_real$separator$disk"
4842                                         separator=$'\n'
4843                                 fi
4844                         fi
4845                 done
4846                 dev_disks_real="$( sort -u <<< "$dev_disks_real" )"
4847                 linked=''
4848                 disk=''
4849                 separator=''
4850         fi
4851
4852         # A_OPTICAL_DRIVE_DATA indexes: not going to use all these, but it's just as easy to build the full
4853         # data array and use what we need from it as to update it later to add features or items
4854         # 0 - true dev path, ie, sr0, hdc
4855         # 1 - dev links to true path
4856         # 2 - device vendor - for hdx drives, vendor model are one string from proc
4857         # 3 - device model
4858         # 4 - device rev version
4859         # 5 - speed
4860         # 6 - multisession support
4861         # 7 - MCN support
4862         # 8 - audio read
4863         # 9 - cdr
4864         # 10 - cdrw
4865         # 11 - dvd read
4866         # 12 - dvdr
4867         # 13 - dvdram
4868         # 14 - state
4869
4870         if [[ -n $dev_disks_real ]];then
4871                 if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
4872                         proc_cdrom="$( cat /proc/sys/dev/cdrom/info 2>/dev/null )"
4873                 fi
4874                 IFS=$'\n'
4875                 A_OPTICAL_DRIVE_DATA=( $(
4876                 for disk in $dev_disks_real
4877                 do
4878                         for linked in $dev_disks_links 
4879                         do
4880                                 if [[ -n $( readlink $linked | grep $disk ) ]];then
4881                                         linked=$( basename $linked )
4882                                         link_list="$link_list$separator$linked"
4883                                         separator='~'
4884                                 fi
4885                         done
4886                         item_string="$disk,$link_list"
4887                         link_list=''
4888                         linked=''
4889                         separator=''
4890                         vendor=''
4891                         model=''
4892                         proc_info_string=''
4893                         rev_number=''
4894                         state=""
4895                         sys_path=''
4896                         # this is only for new sd type paths in /sys, otherwise we'll use /proc/ide
4897                         if [[ -z $( grep '^hd' <<< $disk ) ]];then
4898                                 sys_path=$( ls /sys/devices/pci*/*/host*/target*/*/block/$disk/uevent 2>/dev/null | sed "s|/block/$disk/uevent||" )
4899                                 # no need to test for errors yet, probably other user systems will require some alternate paths though
4900                                 if [[ -n $sys_path ]];then
4901                                         vendor=$( cat $sys_path/vendor 2>/dev/null )
4902                                         model=$( cat $sys_path/model 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
4903                                         state=$( cat $sys_path/state 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
4904                                         rev_number=$( cat $sys_path/rev 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/,//g' )
4905                                 fi
4906                         elif [[ -e /proc/ide/$disk/model ]];then
4907                                 vendor=$( cat /proc/ide/$disk/model 2>/dev/null )
4908                         fi
4909                         if [[ -n $vendor ]];then
4910                                 vendor=$( gawk '
4911                                 BEGIN {
4912                                         IGNORECASE=1
4913                                 }
4914                                 {
4915                                         gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
4916                                         sub(/TSSTcorp/, "TSST ", $0) # seen more than one of these weird ones
4917                                         gsub(/,/, " ", $0)
4918                                         gsub(/^[[:space:]]*|[[:space:]]*$/, "", $0)
4919                                         gsub(/ [[:space:]]+/, " ", $0)
4920                                         print $0
4921                                 }'      <<< $vendor
4922                                 )
4923                         fi
4924                         # this needs to run no matter if there's proc data or not to create the array comma list
4925                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
4926                                 proc_info_string=$( gawk -v diskId=$disk '
4927                                 BEGIN {
4928                                         IGNORECASE=1
4929                                         position=""
4930                                         speed=""
4931                                         multisession=""
4932                                         mcn=""
4933                                         audio=""
4934                                         cdr=""
4935                                         cdrw=""
4936                                         dvd=""
4937                                         dvdr=""
4938                                         dvdram=""
4939                                 }
4940                                 # first get the position of the device name from top field
4941                                 # we will use this to get all the other data for that column
4942                                 /drive name:/ {
4943                                         for ( position=3; position <= NF; position++ ) {
4944                                                 if ( $position == diskId ) {
4945                                                         break
4946                                                 }
4947                                         }
4948                                 }
4949                                 /drive speed:/ {
4950                                         speed = $position
4951                                 }
4952                                 /Can read multisession:/ {
4953                                         multisession=$( position + 1 )
4954                                 }
4955                                 /Can read MCN:/ {
4956                                         mcn=$( position + 1 )
4957                                 }
4958                                 /Can play audio:/ {
4959                                         audio=$( position + 1 )
4960                                 }
4961                                 /Can write CD-R:/ {
4962                                         cdr=$( position + 1 )
4963                                 }
4964                                 /Can write CD-RW:/ {
4965                                         cdrw=$( position + 1 )
4966                                 }
4967                                 /Can read DVD:/ {
4968                                         dvd=$( position + 1 )
4969                                 }
4970                                 /Can write DVD-R:/ {
4971                                         dvdr=$( position + 1 )
4972                                 }
4973                                 /Can write DVD-RAM:/ {
4974                                         dvdram=$( position + 1 )
4975                                 }
4976                                 END {
4977                                         print speed "," multisession "," mcn "," audio "," cdr "," cdrw "," dvd "," dvdr "," dvdram
4978                                 }
4979                                 ' <<< "$proc_cdrom"
4980                                 )
4981                         fi
4982                         item_string="$item_string,$vendor,$model,$rev_number,$proc_info_string,$state"
4983                         echo $item_string
4984                 done
4985                 ) )
4986                 IFS="$ORIGINAL_IFS"
4987         fi
4988         temp_array=${A_OPTICAL_DRIVE_DATA[@]}
4989         log_function_data "A_OPTICAL_DRIVE_DATA: $temp_array"
4990         eval $LOGFE
4991 }
4992
4993 get_partition_data()
4994 {
4995         eval $LOGFS
4996         
4997         local a_partition_working='' dev_item='' temp_array=''
4998         #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660'
4999         # df doesn't seem to work in script with variables like at the command line
5000         # added devfs linprocfs sysfs fdescfs which show on debian kfreebsd kernel output
5001         local main_partition_data="$( 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 )"
5002         local swap_data="$( swapon -s )"
5003         # set dev disk label/uuid data globals
5004         get_partition_uuid_label_data 'label'
5005         get_partition_uuid_label_data 'uuid'
5006         
5007         log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data"
5008         
5009         # new kernels/df have rootfs and / repeated, creating two entries for the same partition
5010         # so check for two string endings of / then slice out the rootfs one, I could check for it
5011         # before slicing it out, but doing that would require the same action twice re code execution
5012         if [[ $( grep -cs '[[:space:]]/$' <<< "$main_partition_data" ) -gt 1 ]];then
5013                 main_partition_data="$( grep -vs '^rootfs' <<< "$main_partition_data" )"
5014         fi
5015         log_function_data 'raw' "main_partition_data_post_rootfs:\n$main_partition_data\n\nswap_data:\n$swap_data"
5016         IFS=$'\n'
5017         # sample line: /dev/sda2     ext3     15G  8.9G  4.9G  65% /home
5018         # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used
5019         ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if
5020         ## the first field is too long, it will occupy its own line, this way we are getting only the needed data
5021         A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk '
5022         BEGIN {
5023                 IGNORECASE=1
5024         }
5025         # this has to be nulled for every iteration so it does not retain value from last iteration
5026         devBase=""
5027         # this is required because below we are subtracting from NF, so it has to be > 5
5028         # the real issue is long file system names that force the wrap of df output: //fileserver/main
5029         # but we still need to handle more dynamically long space containing file names, but later.
5030         # Using df -P should fix this, ie, no wrapping of line lines, but leaving this for now
5031         ( NF < 6 ) && ( $0 !~ /[0-9]+%/ ) {
5032                 # set the dev location here for cases of wrapped output
5033                 if ( NF == 1 ){
5034                         devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
5035                 }
5036                 getline
5037         }
5038         # next set devBase if it didn not get set above here
5039         ( $1 ~ /^\/dev\// ) && ( devBase == "" ) {
5040                 devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
5041         }
5042         # this handles yet another fredforfaen special case where a mounted drive
5043         # has the search string in its name
5044         $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ {
5045                 print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," $(NF - 5) "," devBase 
5046         }
5047         # skip all these, including the first, header line. Use the --exclude-type
5048         # to handle new filesystems types we do not want listed here
5049         $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ {
5050                 # this is to avoid file systems with spaces in their names, that will make
5051                 # the test show the wrong data in each of the fields, if no x%, then do not use
5052                 # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name
5053                 if ( $(NF - 1) ~ /[0-9]+%/ ) {
5054                         print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," $(NF - 5) "," devBase 
5055                 }
5056                 # these two cases construct the space containing name
5057                 else if ( $(NF - 2) ~ /[0-9]+%/ ) {
5058                         print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," $(NF - 6) "," devBase
5059                 }
5060                 else if ( $(NF - 3) ~ /[0-9]+%/ ) {
5061                         print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," $(NF - 7) "," devBase 
5062                 }
5063         }
5064         ' )
5065         
5066         # now add the swap partition data, don't want to show swap files, just partitions,
5067         # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this
5068         # data, it's the same exact output as swapon -s
5069         $( echo "$swap_data" | gawk '
5070         BEGIN {
5071                 swapCounter = 1
5072         }
5073         /^\/dev/ {
5074                 size = sprintf( "%.2f", $3*1024/1000**3 )
5075                 devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
5076                 used = sprintf( "%.2f", $4*1024/1000**3 )
5077                 percentUsed = sprintf( "%.0f", ( $4/$3 )*100 )
5078                 print "swap-" swapCounter "," size "GB," used "GB," percentUsed "%,main," "swap," devBase
5079                 swapCounter = ++swapCounter
5080         }' ) )
5081         IFS="$ORIGINAL_IFS"
5082         
5083         temp_array=${A_PARTITION_DATA[@]}
5084         log_function_data "1: A_PARTITION_DATA:\n$temp_array"
5085         
5086         # now we'll handle some fringe cases where irregular df -hT output shows /dev/disk/.. instead of 
5087         # /dev/h|sdxy type data for column 1, . A_PARTITION_DATA[6]
5088         # Here we just search for the uuid/label and then grab the end of the line to get the right dev item.
5089         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
5090         do
5091                 IFS=","
5092                 a_partition_working=( ${A_PARTITION_DATA[i]} )
5093                 IFS="$ORIGINAL_IFS"
5094                 dev_item='' # reset each loop
5095                 # note: for swap this will already be set
5096                 if [[ -n $( grep -E '(by-uuid|by-label)' <<< ${a_partition_working[6]} ) ]];then
5097                         if [[ -n $DEV_DISK_UUID ]];then
5098                                 dev_item=$( echo "$DEV_DISK_UUID" | gawk '
5099                                         /'$( basename ${a_partition_working[6]} )'/ {
5100                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
5101                                                 print item
5102                                         }' )
5103                         fi
5104                         # if we didn't find anything for uuid try label
5105                         if [[ -z $dev_item && -n $DEV_DISK_LABEL ]];then
5106                                 dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
5107                                         /'$( basename ${a_partition_working[6]} )'/ {
5108                                                 item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
5109                                                 print item
5110                                         }' )
5111                         fi
5112                         if [[ -n $dev_item ]];then
5113                                 # assemble everything we could get for dev/h/dx, label, and uuid
5114                                 IFS=","
5115                                 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
5116                                 IFS="$ORIGINAL_IFS"
5117                         fi
5118                 fi
5119         done
5120         temp_array=${A_PARTITION_DATA[@]}
5121         log_function_data "2: A_PARTITION_DATA:\n$temp_array"
5122         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
5123                 get_partition_data_advanced
5124         fi
5125         eval $LOGFE
5126 }
5127
5128 # first get the locations of the mount points for label/uuid detection
5129 get_partition_data_advanced()
5130 {
5131         eval $LOGFS
5132         local a_partition_working='' dev_partition_data=''
5133         local dev_item='' dev_label='' dev_uuid='' temp_array=''
5134         local mount_point=''
5135         # set dev disk label/uuid data globals
5136         get_partition_uuid_label_data 'label'
5137         get_partition_uuid_label_data 'uuid'
5138
5139         if [[ $B_MOUNTS_FILE == 'true' ]];then
5140                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
5141                 do
5142                         IFS=","
5143                         a_partition_working=( ${A_PARTITION_DATA[i]} )
5144                         IFS="$ORIGINAL_IFS"
5145                         
5146                         # note: for swap this will already be set
5147                         if [[ -z ${a_partition_working[6]} ]];then
5148                                 mount_point=$( sed 's|/|\\/|g'  <<< ${a_partition_working[0]} )
5149                                 #echo mount_point $mount_point
5150                                 dev_partition_data=$( gawk '
5151                                 BEGIN {
5152                                         IGNORECASE = 1
5153                                         partition = ""
5154                                         partTemp = ""
5155                                 }
5156                                 # trying to handle space in name
5157 #                               gsub( /\\040/, " ", $0 )
5158                                 /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" {
5159                                         # initialize the variables
5160                                         label = ""
5161                                         uuid = ""
5162
5163                                         # slice out the /dev
5164                                         partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 )
5165                                         # label and uuid can occur for root, set partition to null now
5166                                         if ( partition ~ /by-label/ ) {
5167                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 )
5168                                                 partition = ""
5169                                         }
5170                                         if ( partition ~ /by-uuid/ ) {
5171                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 )
5172                                                 partition = ""
5173                                         }
5174
5175                                         # handle /dev/root for / id
5176                                         if ( partition == "root" ) {
5177                                                 # if this works, great, otherwise, just set this to null values
5178                                                 partTemp="'$( readlink /dev/root 2>/dev/null )'"
5179                                                 if ( partTemp != "" ) {
5180                                                         if ( partTemp ~ /[hsv]d[a-z][0-9]{1,2}/ ) {
5181                                                                 partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp )
5182                                                         }
5183                                                         else if ( partTemp ~ /by-uuid/ ) {
5184                                                                 uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp )
5185                                                                 partition="" # set null to let real location get discovered
5186                                                         }
5187                                                         else if ( partTemp ~ /by-label/ ) {
5188                                                                 label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp )
5189                                                                 partition="" # set null to let real location get discovered
5190                                                         }
5191                                                 }
5192                                                 else {
5193                                                         partition = ""
5194                                                         label = ""
5195                                                         uuid = ""
5196                                                 }
5197                                         }
5198                                         print partition "," label "," uuid
5199                                 }'      $FILE_MOUNTS )
5200
5201                                 # assemble everything we could get for dev/h/dx, label, and uuid
5202                                 IFS=","
5203                                 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
5204                                 IFS="$ORIGINAL_IFS"
5205                         fi
5206                         ## now we're ready to proceed filling in the data
5207                         IFS=","
5208                         a_partition_working=( ${A_PARTITION_DATA[i]} )
5209                         IFS="$ORIGINAL_IFS"
5210
5211                         dev_item=${a_partition_working[6]}
5212                         dev_label=${a_partition_working[7]}
5213                         dev_uuid=${a_partition_working[8]}
5214                         
5215                         # then if dev data/uuid is incomplete, try to get missing piece
5216                         # it's more likely we'll get a uuid than a label. But this should get the
5217                         # dev item set no matter what, so then we can get the rest of any missing data
5218                         # first we'll get the dev_item if it's missing
5219                         if [[ -z $dev_item ]];then
5220                                 if [[ -n $DEV_DISK_UUID && -n $dev_uuid ]];then
5221                                         dev_item=$( echo "$DEV_DISK_UUID" | gawk '
5222                                                 /'$dev_uuid'/ {
5223                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
5224                                                         print item
5225                                                 }' )
5226                                 elif [[ -n $DEV_DISK_LABEL && -n $dev_label ]];then
5227                                         dev_item=$( echo "$DEV_DISK_LABEL" | gawk '
5228                                                 # first we need to change space x20 in by-label back to a real space
5229                                                 #gsub( /x20/, " ", $0 )
5230                                                 # then we can see if the string is there
5231                                                 /'$dev_label'/ {
5232                                                         item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF )
5233                                                         print item
5234                                                 }' )
5235                                 fi
5236                         fi
5237                         # this can trigger all kinds of weird errors if it is a non /dev path, like: remote:/machine/name
5238                         if [[ -n $dev_item && -z $( grep -E '(^//|:/)' <<< $dev_item ) ]];then
5239                                 if [[ -n $DEV_DISK_UUID && -z $dev_uuid ]];then
5240                                         dev_uuid=$( echo "$DEV_DISK_UUID" | gawk  '
5241                                         /'$dev_item'$/ {
5242                                                 print $(NF - 2)
5243                                         }' )
5244                                 fi
5245                                 if [[ -n $DEV_DISK_LABEL && -z $dev_label ]];then
5246                                         dev_label=$( echo "$DEV_DISK_LABEL" | gawk '
5247                                         /'$dev_item'$/ {
5248                                                 print $(NF - 2)
5249                                         }' )
5250                                 fi
5251                         fi
5252
5253                         # assemble everything we could get for dev/h/dx, label, and uuid
5254                         IFS=","
5255                         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
5256                         IFS="$ORIGINAL_IFS"
5257                 done
5258                 log_function_data 'cat' "$FILE_MOUNTS"
5259         fi
5260         temp_array=${A_PARTITION_DATA[@]}
5261         log_function_data "3-advanced: A_PARTITION_DATA:\n$temp_array"
5262         eval $LOGFE
5263 }
5264
5265 # args: $1 - uuid/label
5266 get_partition_uuid_label_data()
5267 {
5268         eval $LOGFS
5269         
5270         # only run these tests once per directory to avoid excessive queries to fs
5271         case $1 in
5272                 label)
5273                         if [[ $B_LABEL_SET != 'true' ]];then
5274                                 if [[ -d /dev/disk/by-label ]];then
5275                                         DEV_DISK_LABEL="$( ls -l /dev/disk/by-label )"
5276                                 fi
5277                                 B_LABEL_SET='true'
5278                         fi
5279                         ;;
5280                 uuid)
5281                         if [[ $B_UUID_SET != 'true' ]];then
5282                                 if [[ -d /dev/disk/by-uuid ]];then
5283                                         DEV_DISK_UUID="$( ls -l /dev/disk/by-uuid )"
5284                                 fi
5285                                 B_UUID_SET='true'
5286                         fi
5287                         ;;
5288         esac
5289         log_function_data 'raw' "DEV_DISK_LABEL:\n$DEV_DISK_LABEL\n\nDEV_DISK_UUID:\n$DEV_DISK_UUID"
5290         # debugging section, uncomment to insert user data
5291 #       DEV_DISK_LABEL='
5292 #
5293 # '
5294 # DEV_DISK_UUID='
5295 #
5296 # '
5297         eval $LOGFE
5298 }
5299
5300 get_patch_version_string()
5301 {
5302         local script_patch_number=$( sed 's/^[0]\+//' <<< $SCRIPT_PATCH_NUMBER )
5303         if [[ -n $script_patch_number ]];then
5304                 script_patch_number="-$script_patch_number"
5305         fi
5306         echo $script_patch_number
5307 }
5308
5309 # args: $1 - type cpu/mem 
5310 get_ps_data()
5311 {
5312         eval $LOGFS
5313         local array_length='' reorder_temp='' i=0 head_tail='' sort_type=''
5314         
5315         # bummer, have to make it more complex here because of reverse sort
5316         # orders in output, pesky lack of support of +rss in old systems
5317         case $1 in
5318                 mem)
5319                         head_tail='head'
5320                         sort_type='-rss'
5321                         ;;
5322                 cpu)
5323                         head_tail='tail'
5324                         sort_type='%cpu'
5325                         ;;
5326         esac
5327         
5328         # throttle potential irc abuse
5329         if [[ $B_RUNNING_IN_SHELL != 'true' && $PS_COUNT -gt 5 ]];then
5330                 PS_THROTTLED=$PS_COUNT
5331                 PS_COUNT=5
5332         fi
5333
5334         IFS=$'\n'
5335         # note that inxi can use a lot of cpu, and can actually show up here as the script runs
5336         A_PS_DATA=( $( ps aux --sort $sort_type | grep -Ev "($SCRIPT_NAME|%CPU|[[:space:]]ps[[:space:]])" | $head_tail -n $PS_COUNT | gawk '
5337         BEGIN {
5338                 IGNORECASE=1
5339                 appName=""
5340                 appPath=""
5341                 appStarterName=""
5342                 appStarterPath=""
5343                 cpu=""
5344                 mem=""
5345                 pid=""
5346                 user=""
5347                 rss=""
5348         }
5349         {
5350                 cpu=$3
5351                 mem=$4
5352                 pid=$2
5353                 user=$1
5354                 rss=sprintf( "%.2f", $6/1024 )
5355                 # have to get rid of [,],(,) eg: [lockd] which break the printout function compare in bash
5356                 gsub(/\[|\]|\(|\)/,"~", $0 )
5357                 if ( $12 ~ /^\// ){
5358                         appStarterPath=$11
5359                         appPath=$12
5360                 }
5361                 else {
5362                         appStarterPath=$11
5363                         appPath=$11
5364                 }
5365                 appStarterName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appStarterPath )
5366                 appName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appPath )
5367                 print appName "," appPath "," appStarterName "," appStarterPath "," cpu "," mem "," pid "," rss "," user
5368         }
5369         ' ) )
5370         # make the array ordered highest to lowest so output looks the way we expect it to
5371         # this isn't necessary for -rss, and we can't make %cpu ordered the other way, so
5372         # need to reverse it here. -rss is used because on older systems +rss is not supported
5373         if [[ $1 == 'cpu' ]];then
5374                 array_length=${#A_PS_DATA[@]}; 
5375                 while (( $i < $array_length/2 ))
5376                 do 
5377                         reorder_temp=${A_PS_DATA[i]}f
5378                         A_PS_DATA[i]=${A_PS_DATA[$array_length-$i-1]}
5379                         A_PS_DATA[$array_length-$i-1]=$reorder_temp
5380                         (( i++ ))
5381                 done 
5382         fi
5383
5384         IFS="$ORIGINAL_IFS"
5385         
5386 #       echo ${A_PS_DATA[@]}
5387         eval $LOGFE
5388 }
5389
5390 # Repos will be added as we get distro package manager data to create the repo data. 
5391 # This method will output the file name also, which is useful to create output that's 
5392 # neat and readable.
5393 get_repo_data()
5394 {
5395         eval $LOGFS
5396         local repo_file='' repo_data_working='' repo_data_working2='' repo_line=''
5397         local apt_file='/etc/apt/sources.list' yum_repo_dir='/etc/yum.repos.d/' yum_conf='/etc/yum.conf'
5398         local pacman_conf='/etc/pacman.conf' pacman_repo_dir='/etc/pacman.d/' pisi_dir='/etc/pisi/'
5399         
5400         # apt - debian, buntus
5401         if [[ -f $apt_file || -d $apt_file.d ]];then
5402                 REPO_DATA="$( grep -Esv '(^[[:space:]]*$|^[[:space:]]*#)' $apt_file $apt_file.d/*.list )"
5403                 REPO_FILE_ID='apt sources'
5404         # yum - fedora, redhat, centos, etc
5405         elif [[ -d $yum_repo_dir || -f $yum_conf ]];then
5406                 # older redhats put their yum data in /etc/yum.conf
5407                 for repo_file in $( ls $yum_repo_dir*.repo $yum_conf 2>/dev/null )
5408                 do
5409                         repo_data_working="$( gawk -v repoFile=$repo_file '
5410                         # construct the string for the print function to work with, file name: data
5411                         function print_line( fileName, repoId, repoUrl ){
5412                                 print fileName ":" repoId repoUrl
5413                         }
5414                         BEGIN {
5415                                 FS="\n"
5416                                 IGNORECASE=1
5417                                 enabledStatus=""
5418                                 repoTitle=""
5419                                 urlData=""
5420                         }
5421                         # this is a hack, assuming that each item has these fields listed, we collect the 3
5422                         # items one by one, then when the url/enabled fields are set, we print it out and
5423                         # reset the data. Not elegant but it works. Note that if enabled was not present
5424                         # we assume it is enabled then, and print the line, reset the variables. This will
5425                         # miss the last item, so it is printed if found in END
5426                         /^\[.+\]/ {
5427                                 if ( urlData != "" && repoTitle != "" ){
5428                                         print_line( repoFile, repoTitle, urlData )
5429                                         enabledStatus=""
5430                                         urlData=""
5431                                         repoTitle=""
5432                                 }
5433                                 gsub( /\[|\]/, "", $1 ) # strip out the brackets
5434                                 repoTitle = $1 " ~ "
5435                         }
5436                         /^(mirrorlist|baseurl)/ {
5437                                 sub( /(mirrorlist|baseurl)=/, "", $1 ) # strip out the field starter
5438                                 urlData = $1
5439                         }
5440                         /^enabled=/ {
5441                                 enabledStatus = $1
5442                         }
5443                         # print out the line if all 3 values are found, otherwise if a new
5444                         # repoTitle is hit above, it will print out the line there instead
5445                         { 
5446                                 if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
5447                                         if ( enabledStatus !~ /enabled=0/ ){
5448                                                 print_line( repoFile, repoTitle, urlData )
5449                                         }
5450                                         enabledStatus=""
5451                                         urlData=""
5452                                         repoTitle=""
5453                                 }
5454                         }
5455                         END {
5456                                 # print the last one if there is data for it
5457                                 if ( urlData != ""  && repoTitle != "" ){
5458                                         print_line( repoFile, repoTitle, urlData )
5459                                 }
5460                         }
5461                         ' $repo_file )"
5462                         
5463                         # then load the global for each file as it gets filled
5464                         if [[ -n $repo_data_working ]];then
5465                                 if [[ -z $REPO_DATA ]];then
5466                                         REPO_DATA="$repo_data_working"
5467                                 else
5468                                         REPO_DATA="$REPO_DATA
5469 $repo_data_working"
5470                                 fi
5471                                 repo_data_working=''
5472                         fi
5473                 done
5474                 REPO_FILE_ID='yum repos'
5475         # pisi - pardus
5476         elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
5477                 REPO_DATA="$( pisi list-repo )"
5478                 # now we need to create the structure: repo info: repo path
5479                 # we do that by looping through the lines of the output and then
5480                 # putting it back into the <data>:<url> format print repos expects to see
5481                 while read repo_line
5482                 do
5483                         repo_line=$( gawk '
5484                         {
5485                                 # need to dump leading/trailing spaces and clear out color codes for irc output
5486                                 sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
5487 #                               gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
5488                                 gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
5489                                 print $0
5490                         }' <<< $repo_line )
5491                         if [[ -n $( grep '://' <<< $repo_line ) ]];then
5492                                 repo_data_working="$repo_data_working:$repo_line\n"
5493                         else
5494                                 repo_data_working="$repo_data_working$repo_line"
5495                         fi
5496                 done <<< "$REPO_DATA"
5497                 # echo and execute the line breaks inserted
5498                 REPO_DATA="$( echo -e $repo_data_working )"
5499                 REPO_FILE_ID='pisi repo'
5500         # pacman - archlinux
5501         elif [[ -f $pacman_conf ]];then
5502                 # get list of mirror include files, trim white space off ends
5503                 repo_data_working="$( gawk '
5504                 BEGIN {
5505                         FS="="
5506                         IGNORECASE=1
5507                 }
5508                 /^[[:space:]]*Include/ {
5509                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
5510                         print $2
5511                 }
5512                 ' $pacman_conf )"
5513                 # sort into unique paths only, to be used to search for server = data
5514                 repo_data_working=$( sort -bu <<< "$repo_data_working" | uniq ) 
5515                 repo_data_working="$repo_data_working $pacman_conf"
5516                 for repo_file in $repo_data_working 
5517                 do
5518                         if [[ -f $repo_file ]];then
5519                                 # inserting a new line after each found / processed match
5520                                 repo_data_working2="$repo_data_working2$( gawk -v repoFile=$repo_file '
5521                                 BEGIN {
5522                                         FS="="
5523                                         IGNORECASE=1
5524                                 }
5525                                 /^[[:space:]]*Server/ {
5526                                         sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
5527                                         print repoFile ":" $2 "\\n"
5528                                 }
5529                                 ' $repo_file )"
5530                         else
5531                                 echo "Error: file listed in $pacman_conf does not exist - $repo_file"
5532                         fi
5533                 done
5534                 # execute line breaks
5535                 REPO_DATA="$( echo -e $repo_data_working2 )"
5536                 REPO_FILE_ID='arch repo servers'
5537         fi
5538         eval $LOGFE
5539 }
5540
5541 get_runlevel_data()
5542 {
5543         eval $LOGFS
5544         local runlvl=''
5545         local runlevel_path=$( type -p runlevel )
5546         if [[ -n $runlevel_path ]];then
5547                 runlvl="$( $runlevel_path | gawk '{ print $2 }' )"
5548         fi
5549         echo $runlvl
5550         eval $LOGFE
5551 }
5552
5553 get_sensors_data()
5554 {
5555         eval $LOGFS
5556         
5557         
5558         local temp_array=''
5559                 
5560         IFS=$'\n'
5561         if [[ -n $Sensors_Data ]];then
5562                 # note: non-configured sensors gives error message, which we need to redirect to stdout
5563                 # also, -F ':' no space, since some cases have the data starting right after,like - :1287
5564                 A_SENSORS_DATA=( $( 
5565                 gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" '
5566                 BEGIN {
5567                         IGNORECASE=1
5568                         core0Temp="" # only if all else fails...
5569                         cpuTemp=""
5570                         cpuTempReal=""
5571                         fanWorking=""
5572                         indexCountaFanMain=0
5573                         indexCountaFanDefault=0
5574                         i=""
5575                         j=""
5576                         moboTemp=""
5577                         moboTempReal=""
5578                         psuTemp=""
5579                         separator=""
5580                         sysFanString=""
5581                         temp1=""
5582                         temp2=""
5583                         tempFanType="" # set to 1 or 2
5584                         tempUnit=""
5585                         tempWorking=""
5586                         tempWorkingUnit=""
5587                 }
5588                 # new data arriving: gpu temp in sensors, have to skip that
5589                 /^('"$SENSORS_GPU_SEARCH"')-pci/ {
5590                         while ( getline && !/^$/ ) {
5591                                 # do nothing, just skip it
5592                         }
5593                 }
5594                 # dumping the extra + signs after testing for them,  nobody has negative temps.
5595                 # also, note gawk treats Â° as a space, so we have to get the C/F data
5596                 # there are some guesses here, but with more sensors samples it will get closer.
5597                 # note: using arrays starting at 1 for all fan arrays to make it easier overall
5598                 # more validation because gensub if fails to get match returns full string, so
5599                 # we have to be sure we are working with the actual real string before assiging
5600                 # data to real variables and arrays. Extracting C/F degree unit as well to use
5601                 # when constructing temp items for array. 
5602                 # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign 
5603                 # used, but it is required in testing regex to avoid error.
5604                 /^(M\/B|MB|SIO|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5605                         moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 )
5606                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5607                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5608                                 tempUnit=tempWorkingUnit
5609                         }
5610                 }
5611                 /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5612                         cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
5613                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5614                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5615                                 tempUnit=tempWorkingUnit
5616                         }
5617                 }
5618                 /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5619                         psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
5620                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5621                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5622                                 tempUnit=tempWorkingUnit
5623                         }
5624                 }
5625                 $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5626                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
5627                         if ( temp1 == "" || tempWorking > 0 ) {
5628                                 temp1=tempWorking
5629                         }
5630                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5631                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5632                                 tempUnit=tempWorkingUnit
5633                         }
5634                 }
5635                 $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5636                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
5637                         if ( temp2 == "" || tempWorking > 0 ) {
5638                                 temp2=tempWorking
5639                         }
5640                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5641                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5642                                 tempUnit=tempWorkingUnit
5643                         }
5644                 }
5645                 
5646                 # final fallback if all else fails, funtoo user showed sensors putting
5647                 # temp on wrapped second line, not handled
5648                 /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
5649                         tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
5650                         if ( core0Temp == "" || tempWorking > 0 ) {
5651                                 core0Temp=tempWorking
5652                         }
5653                         tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
5654                         if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
5655                                 tempUnit=tempWorkingUnit
5656                         }
5657                 }
5658                 
5659                 # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before
5660                 # $2 starts (like so :1234 RPM), so skip that space test in regex
5661                 /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5662                         aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5663                 }
5664                 /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5665                         aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5666                 }
5667                 /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5668                         aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5669                 }
5670                 # note that the counters are dynamically set for fan numbers here
5671                 # otherwise you could overwrite eg aux fan2 with case fan2 in theory
5672                 # note: cpu/mobo/ps are 1/2/3
5673                 # NOTE: test: ! i in array does NOT work, this appears to be an awk/gawk bug
5674                 /^(AUX(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5675                         for ( i = 4; i < 7; i++ ){
5676                                 if ( i in aFanMain ){
5677                                         ##
5678                                 }
5679                                 else {
5680                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5681                                         break
5682                                 }
5683                         }
5684                 }
5685                 /^(AUX([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5686                         for ( i = 5; i < 30; i++ ){
5687                                 if ( i in aFanMain ) {
5688                                         ##
5689                                 }
5690                                 else {
5691                                         sysFanNu = i
5692                                         aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5693                                         break
5694                                 }
5695                         }
5696                 }
5697                 # in rare cases syntax is like: fan1: xxx RPM
5698                 /^(FAN(1)?[ \t:])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5699                         aFanDefault[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5700                 }
5701                 /^FAN([2-9]|1[0-9])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
5702                         fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
5703                         sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 )
5704                         if ( sysFanNu ~ /^([0-9]+)$/ ) {
5705                                 # add to array if array index does not exist OR if number is > existing number
5706                                 if ( sysFanNu in aFanDefault ) {
5707                                         if ( fanWorking >= aFanDefault[sysFanNu] ) {
5708                                                 aFanDefault[sysFanNu]=fanWorking
5709                                         }
5710                                 }
5711                                 else {
5712                                         aFanDefault[sysFanNu]=fanWorking
5713                                 }
5714                         }
5715                 }
5716                 
5717                 END {
5718                         # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo:
5719                         # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment
5720                         if ( temp1 != "" && temp2 != "" ){
5721                                 if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) {
5722                                         tempFanType=userCpuNo
5723                                 }
5724                                 else {
5725                                         # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed
5726                                         # but only if other fan speed is 0
5727                                         if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) {
5728                                                 tempFanType=2
5729                                         }
5730                                         else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) {
5731                                                 tempFanType=1
5732                                         }
5733                                         # then handle the standard case if these fringe cases are false
5734                                         else if ( temp1 >= temp2 ) {
5735                                                 tempFanType=1
5736                                         }
5737                                         else {
5738                                                 tempFanType=2
5739                                         }
5740                                 }
5741                         }
5742                         # need a case for no temps at all reported, like with old intels
5743                         else if ( temp2 == "" && cpuTemp == "" ){
5744                                 if ( temp1 == "" && moboTemp == "" ){
5745                                         tempFanType=1
5746                                 }
5747                                 else if ( temp1 != "" && moboTemp == "" ){
5748                                         tempFanType=1
5749                                 }
5750                                 else if ( temp1 != "" && moboTemp != "" ){
5751                                         tempFanType=1
5752                                 }
5753                         }
5754                         
5755                         # then get the real cpu temp, best guess is hottest is real
5756                         if ( cpuTemp != "" ){
5757                                 cpuTempReal=cpuTemp
5758                         }
5759                         else if ( tempFanType != "" ){
5760                                 if ( tempFanType == 1 ){
5761                                         cpuTempReal=temp1
5762                                 }
5763                                 else {
5764                                         cpuTempReal=temp2
5765                                 }
5766                         }
5767                         else {
5768                                 cpuTempReal=temp1
5769                         }
5770                         # if all else fails, use core0 temp if it is present and cpu is null
5771                         if ( cpuTempReal == "" && core0Temp != "" ) {
5772                                 cpuTempReal=core0Temp
5773                         }
5774
5775                         # then the real mobo temp
5776                         if ( moboTemp != "" ){
5777                                 moboTempReal=moboTemp
5778                         }
5779                         else if ( tempFanType != "" ){
5780                                 if ( tempFanType == 1 ) {
5781                                         moboTempReal=temp2
5782                                 }
5783                                 else {
5784                                         moboTempReal=temp1
5785                                 }
5786                         }
5787                         else {
5788                                 moboTempReal=temp2
5789                         }
5790                         # then set the cpu fan speed
5791                         if ( aFanMain[1] == "" ) {
5792                                 # note, you cannot test for aFanDefault[1] or [2] != "" 
5793                                 # because that creates an array item in gawk just by the test itself
5794                                 if ( tempFanType == 1 && 1 in aFanDefault ) {
5795                                         aFanMain[1]=aFanDefault[1]
5796                                         aFanDefault[1]=""
5797                                 }
5798                                 else if ( tempFanType == 2 && 2 in aFanDefault ) {
5799                                         aFanMain[1]=aFanDefault[2]
5800                                         aFanDefault[2]=""
5801                                 }
5802                         }
5803
5804                         # then we need to get the actual numeric max array count for both fan arrays
5805                         for (i = 0; i <= 29; i++) {
5806                                 if ( i in aFanMain && i > indexCountaFanMain ) {
5807                                         indexCountaFanMain=i
5808                                 }
5809                         }
5810                         for (i = 0; i <= 14; i++) {
5811                                 if ( i in aFanDefault && i > indexCountaFanDefault ) {
5812                                         indexCountaFanDefault=i
5813                                 }
5814                         }
5815                         
5816                         # clear out any duplicates. Primary fan real trumps fan working always if same speed
5817                         for (i = 1; i <= indexCountaFanMain; i++) {
5818                                 if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) {
5819                                         for (j = 1; j <= indexCountaFanDefault; j++) {
5820                                                 if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) {
5821                                                         aFanDefault[j] = ""
5822                                                 }
5823                                         }
5824                                 }
5825                         }
5826
5827                         # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo
5828                         # note that gawk is returning true for some test cases when aFanDefault[j] < 5000
5829                         # which has to be a gawk bug, unless there is something really weird with arrays
5830                         # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually 
5831                         # assign that value below, the > 5000 test works again, and a print of the value
5832                         # shows the proper value, so the corruption might be internal in awk. 
5833                         # Note: gensub is the culprit I think, assigning type string for range 501-1000 but 
5834                         # type integer for all others, this triggers true for >
5835                         for (j = 1; j <= indexCountaFanDefault; j++) {
5836                                 if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) {
5837                                         aFanMain[2] = aFanDefault[j]
5838                                         aFanDefault[j] = ""
5839                                         # then add one if required for output
5840                                         if ( indexCountaFanMain < 2 ) {
5841                                                 indexCountaFanMain = 2
5842                                         }
5843                                 }
5844                         }
5845
5846                         # then construct the sys_fan string for echo, note that iteration 1
5847                         # makes: fanDefaultString separator null, ie, no space or ,
5848                         for (j = 1; j <= indexCountaFanDefault; j++) {
5849                                 fanDefaultString = fanDefaultString separator aFanDefault[j]
5850                                 separator=","
5851                         }
5852                         separator="" # reset to null for next loop
5853                         # then construct the sys_fan string for echo
5854                         for (j = 1; j <= indexCountaFanMain; j++) {
5855                                 fanMainString = fanMainString separator aFanMain[j]
5856                                 separator=","
5857                         }
5858                         
5859                         # and then build the temps:
5860                         if ( moboTempReal != "" ) {
5861                                 moboTempReal = moboTempReal tempUnit
5862                         }
5863                         if ( cpuTempReal != "" ) {
5864                                 cpuTempReal = cpuTempReal tempUnit
5865                         }
5866                         
5867                         # if they are ALL null, print error message. psFan is not used in output currently
5868                         if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) {
5869                                 print "No active sensors found. Have you configured your sensors yet?"
5870                         }
5871                         else {
5872                                 # then build array arrays: 
5873                                 print cpuTempReal "," moboTempReal "," psuTemp
5874                                 # this is for output, a null print line does NOT create a new array index in bash
5875                                 if ( fanMainString == "" ) {
5876                                         fanMainString=","
5877                                 }
5878                                 print fanMainString
5879                                 print fanDefaultString
5880                         }
5881                 }' <<< "$Sensors_Data"
5882                 ) )
5883         # the error case needs to go here because we are setting special array delimiter ','
5884         else
5885                 A_SENSORS_DATA=( "You do not have the sensors app installed." )
5886         fi
5887         
5888         IFS="$ORIGINAL_IFS"
5889         temp_array=${A_SENSORS_DATA[@]}
5890         log_function_data "A_SENSORS_DATA: $temp_array"
5891 #       echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
5892         eval $LOGFE
5893 }
5894
5895 get_sensors_output()
5896 {
5897         local sensors_path=$( type -p sensors ) sensors_data=''
5898         
5899         if [[ -n $sensors_path ]];then
5900                 sensors_data="$( $sensors_path 2>/dev/null )"
5901                 if [[ -n "$sensors_data" ]];then
5902                         # make sure the file ends in newlines then characters, the newlines are lost in the echo unless
5903                         # the data ends in some characters
5904                         sensors_data="$sensors_data\n\n###" 
5905                 fi
5906         fi
5907         echo -e "$sensors_data"
5908 }
5909
5910 get_unmounted_partition_data()
5911 {
5912         eval $LOGFS
5913         local a_unmounted_working='' mounted_partitions='' separator='' unmounted_fs=''
5914         local dev_working='' uuid_working='' label_working=''
5915         
5916         if [[ $B_PARTITIONS_FILE == 'true' ]];then
5917                 # set dev disk label/uuid data globals
5918                 get_partition_uuid_label_data 'label'
5919                 get_partition_uuid_label_data 'uuid'
5920                 
5921                 # create list for slicing out the mounted partitions
5922                 for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
5923                 do
5924                         IFS=","
5925                         a_unmounted_working=( ${A_PARTITION_DATA[i]} )
5926                         IFS="$ORIGINAL_IFS"
5927                         if [[ -n ${a_unmounted_working[6]} ]];then
5928                                 mounted_partitions="$mounted_partitions$separator${a_unmounted_working[6]}"
5929                                 separator='|'
5930                         fi
5931                 done
5932         
5933                 A_UNMOUNTED_PARTITION_DATA=( $( grep -Ev '('$mounted_partitions')$' $FILE_PARTITIONS | gawk '
5934                 BEGIN {
5935                         IGNORECASE=1
5936                 }
5937                 # note that size 1 means it is a logical extended partition container
5938                 # lvm might have dm-1 type syntax
5939                 # need to exclude loop type file systems, squashfs for example
5940                 /[a-z][0-9]+$|dm-[0-9]+$/ && $3 != 1 && $NF !~ /loop/ {
5941                         size = sprintf( "%.2f", $3*1024/1000**3 )
5942                         print $4 "," size "G"
5943                 }' ) )
5944
5945                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
5946                 do
5947                         IFS=","
5948                         a_unmounted_working=( ${A_UNMOUNTED_PARTITION_DATA[i]} )
5949                         IFS="$ORIGINAL_IFS"
5950                         
5951                         label_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_LABEL"  | gawk '{
5952                                 print $(NF - 2)
5953                         }' )
5954                         uuid_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_UUID"  | gawk '{
5955                                 print $(NF - 2)
5956                         }' )
5957                         unmounted_fs=$( get_unmounted_partition_filesystem "/dev/${a_unmounted_working[0]}" )
5958                         
5959                         IFS=","
5960                         A_UNMOUNTED_PARTITION_DATA[i]=${a_unmounted_working[0]}","${a_unmounted_working[1]}","$label_working","$uuid_working","$unmounted_fs
5961                         IFS="$ORIGINAL_IFS"
5962                 done
5963         fi
5964 #       echo "${A_PARTITION_DATA[@]}"
5965 #       echo "${A_UNMOUNTED_PARTITION_DATA[@]}"
5966         eval $LOGFE
5967 }
5968
5969 # a few notes, normally file -s requires root, but you can set user rights in /etc/sudoers.
5970 # list of file systems: http://en.wikipedia.org/wiki/List_of_file_systems
5971 # args: $1 - /dev/<disk><part> to be tested for
5972 get_unmounted_partition_filesystem()
5973 {
5974         eval $LOGFS
5975         local partition_filesystem='' sudo_command=''
5976         
5977         if [[ $B_FILE_TESTED != 'true' ]];then
5978                 B_FILE_TESTED='true'
5979                 FILE_PATH=$( type -p file )
5980         fi
5981         
5982         if [[ $B_SUDO_TESTED != 'true' ]];then
5983                 B_SUDO_TESTED='true'
5984                 SUDO_PATH=$( type -p sudo )
5985         fi
5986         
5987         if [[ -n $FILE_PATH && -n $1 ]];then
5988                 # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
5989                 # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
5990                 # important: -n makes it non interactive, no prompt for password
5991                 if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
5992                         sudo_command='sudo -n '
5993                 fi
5994                 # this will fail if regular user and no sudo present, but that's fine, it will just return null
5995                 # note the hack that simply slices out the first line if > 1 items found in string
5996                 # also, if grub/lilo is on partition boot sector, no file system data is available
5997                 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 '.*' )
5998                 if [[ -n $partition_filesystem ]];then
5999                         echo $partition_filesystem
6000                 fi
6001         fi
6002         eval $LOGFE
6003 }
6004
6005 ## return uptime string
6006 get_uptime()
6007 {
6008         eval $LOGFS
6009         ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
6010         local uptime_value="$( uptime | gawk '{
6011                 a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
6012                 print a
6013         }' )"
6014         echo "$uptime_value"
6015         log_function_data "uptime_value: $uptime_value"
6016         eval $LOGFE
6017 }
6018
6019 #### -------------------------------------------------------------------
6020 #### special data handling for specific options and conditions
6021 #### -------------------------------------------------------------------
6022
6023 # args: $1 - string to strip color code characters out of
6024 # returns count of string length minus colors
6025 calculate_line_length()
6026 {
6027         local string="$1"
6028         # ansi: \e[1;34m irc: \x0312
6029         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 )
6030         count=$( wc -c <<< $string )
6031         echo $count
6032 }
6033
6034 ## multiply the core count by the data to be calculated, bmips, cache
6035 # args: $1 - string to handle; $2 - cpu count
6036 calculate_multicore_data()
6037 {
6038         eval $LOGFS
6039         local string_number=$1 string_data=''
6040
6041         if [[ -n $( grep -Ei '( mb| kb)' <<< $1 ) ]];then
6042                 string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output
6043                 string_number=$( gawk '{print $1}' <<< $1 )
6044         fi
6045         # handle weird error cases where it's not a number
6046         if [[ -n $( grep -E '^[0-9\.,]+$' <<< $string_number ) ]];then
6047                 string_number=$( echo $string_number $2 | gawk '{
6048                         total = $1*$2
6049                         print total
6050                 }' )
6051         elif [[ $string_number == '' ]];then
6052                 string_number='Not Available'
6053         else
6054                 # I believe that the above returns 'unknown' by default so no need for extra text
6055                 string_number="$string_number "
6056         fi
6057         echo "$string_number$string_data"
6058         log_function_data "string_numberstring_data: $string_number$string_data"
6059         eval $LOGFE
6060 }
6061
6062 # prints out shortened list of flags, the main ones of interest
6063 # args: $1 - string of cpu flags to process
6064 process_cpu_flags()
6065 {
6066         eval $LOGFS
6067         # must have a space after last item in list for RS=" "
6068         local cpu_flags_working="$1 "
6069         
6070         # nx = AMD stack protection extensions
6071         # lm = Intel 64bit extensions
6072         # sse, sse2, pni = sse1,2,3,4,5 gfx extensions
6073         # svm = AMD pacifica virtualization extensions
6074         # vmx = Intel IVT (vanderpool) virtualization extensions
6075         cpu_flags=$( 
6076         echo "$cpu_flags_working" | gawk '
6077         BEGIN {
6078                 RS=" "
6079                 count = 0
6080                 i = 1 # start at one because of for increment issue
6081                 flag_string = ""
6082         }
6083         /^(lm|nx|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/ {
6084                 if ( $0 == "pni" ){
6085                         a_flags[i] = "sse3"
6086                 }
6087                 else {
6088                         a_flags[i] = $0
6089                 }
6090                 i++
6091         }
6092         END {
6093                 count = asort( a_flags )
6094                 # note: why does gawk increment before the loop and not after? weird.
6095                 for ( i=0; i <= count; i++ ){
6096                         if ( flag_string == "" ) {
6097                                 flag_string = a_flags[i] 
6098                         }
6099                         else {
6100                                 flag_string = flag_string " " a_flags[i]
6101                         }
6102                 }
6103                 print flag_string
6104         }' 
6105         )
6106
6107         #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' '))
6108         if [[ -z $cpu_flags ]];then
6109                 cpu_flags="-"
6110         fi
6111         echo "$cpu_flags"
6112         log_function_data "cpu_flags: $cpu_flags"
6113         eval $LOGFE
6114 }
6115
6116 #### -------------------------------------------------------------------
6117 #### print and processing of output data
6118 #### -------------------------------------------------------------------
6119
6120 #### MASTER PRINT FUNCTION - triggers all line item print functions
6121 ## main function to print out, master for all sub print functions.
6122 print_it_out()
6123 {
6124         eval $LOGFS
6125         # note that print_it_out passes local variable values on to its children,
6126         # and in some cases, their children, with Lspci_Data
6127         local Lspci_Data='' # only for verbose
6128
6129         if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then
6130                 print_short_data
6131         else
6132                 Lspci_Data="$( get_lspci_data )"
6133                 if [[ $B_SHOW_SYSTEM == 'true' ]];then
6134                         print_system_data
6135                 fi
6136                 if [[ $B_SHOW_MACHINE == 'true' ]];then
6137                         print_machine_data
6138                 fi
6139                 if [[ $B_SHOW_BASIC_CPU == 'true' || $B_SHOW_CPU == 'true' ]];then
6140                         print_cpu_data
6141                 fi
6142                 if [[ $B_SHOW_GRAPHICS == 'true' ]];then
6143                         print_gfx_data
6144                 fi
6145                 if [[ $B_SHOW_AUDIO == 'true' ]];then
6146                         print_audio_data
6147                 fi
6148                 if [[ $B_SHOW_NETWORK == 'true' ]];then
6149                         print_networking_data
6150                 fi
6151                 if [[ $B_SHOW_DISK_TOTAL == 'true' || $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
6152                         print_hard_disk_data
6153                 fi
6154                 if [[ $B_SHOW_PARTITIONS == 'true' ]];then
6155                         print_partition_data
6156                 fi
6157                 if [[ $B_SHOW_UNMOUNTED_PARTITIONS == 'true' ]];then
6158                         print_unmounted_partition_data
6159                 fi
6160                 if [[ $B_SHOW_SENSORS == 'true' ]];then
6161                         print_sensors_data
6162                 fi
6163                 if [[ $B_SHOW_REPOS == 'true' ]];then
6164                         print_repo_data
6165                 fi
6166                 if [[ $B_SHOW_PS_CPU_DATA == 'true' || $B_SHOW_PS_MEM_DATA == 'true' ]];then
6167                         print_ps_data
6168                 fi
6169                 if [[ $B_SHOW_INFO == 'true' ]];then
6170                         print_info_data
6171                 fi
6172         fi
6173         eval $LOGFE
6174 }
6175
6176 #### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0
6177 # all the get data stuff is loaded here to keep execution time down for single line print commands
6178 # these will also be loaded in each relevant print function for long output
6179 print_short_data()
6180 {
6181         eval $LOGFS
6182         local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' )
6183         local processes="$(( $( ps aux | wc -l ) - 1 ))"
6184         local short_data='' i='' b_background_black='false'
6185         local memory=$( get_memory_data )
6186         local up_time="$( get_uptime )"
6187
6188         # set A_CPU_CORE_DATA
6189         get_cpu_core_count
6190         local cpc_plural='' cpu_count_print='' model_plural=''
6191         local cpu_physical_count=${A_CPU_CORE_DATA[0]}
6192         local cpu_core_count=${A_CPU_CORE_DATA[3]}
6193         local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
6194         local cpu_type=${A_CPU_CORE_DATA[2]}
6195
6196         if [[ $cpu_physical_count -gt 1 ]];then
6197                 cpc_plural='(s)'
6198                 model_plural='s'
6199                 cpu_count_print="$cpu_physical_count "
6200         fi
6201
6202         local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
6203 #       local cpu_core_count=${A_CPU_CORE_DATA[0]}
6204
6205         # load A_HDD_DATA
6206         get_hdd_data_basic
6207         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
6208         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
6209         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
6210         IFS=","
6211         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
6212         IFS="$ORIGINAL_IFS"
6213         local hdd_capacity=${a_hdd_basic_working[0]}
6214         local hdd_used=${a_hdd_basic_working[1]}
6215
6216         # load A_CPU_DATA
6217         get_cpu_data
6218
6219         IFS=","
6220         local a_cpu_working=(${A_CPU_DATA[0]})
6221         IFS="$ORIGINAL_IFS"
6222         local cpu_model="${a_cpu_working[0]}"
6223         ## assemble data for output
6224         local cpu_clock="${a_cpu_working[1]}" # old CPU3
6225         # this gets that weird min/max final array item
6226         local min_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
6227         local min_max_clock=${A_CPU_DATA[$min_max_clock_nu]}
6228         local script_patch_number=$( get_patch_version_string )
6229
6230         #set_color_scheme 12
6231         if [[ $B_RUNNING_IN_SHELL == 'false' ]];then
6232                 for i in $C1 $C2 $CN
6233                 do
6234                         case "$i" in
6235                                 "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN")
6236                                         b_background_black='true'
6237                                         ;;
6238                         esac
6239                 done
6240                 if [[ $b_background_black == 'true' ]];then
6241                         for i in C1 C2 CN
6242                         do
6243                                 ## these need to be in quotes, don't know why
6244                                 if [[ ${!i} == $NORMAL ]];then
6245                                         declare $i="${!i}15,1"
6246                                 else
6247                                         declare $i="${!i},1"
6248                                 fi
6249                         done
6250                         #C1="${C1},1"; C2="${C2},1"; CN="${CN},1"
6251                 fi
6252         fi
6253         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}"
6254
6255         if [[ $SHOW_IRC -gt 0 ]];then
6256                 short_data="${short_data}${C1}Client${C2}${SEP1}${IRC_CLIENT}${IRC_CLIENT_VERSION}${SEP2}"
6257         fi
6258         short_data="${short_data}${C1}$SCRIPT_NAME${C2}${SEP1}$SCRIPT_VERSION_NUMBER$script_patch_number${SEP2}${CN}"
6259         if [[ $SCHEME -gt 0 ]];then
6260                 short_data="${short_data} $NORMAL"
6261         fi
6262         print_screen_output "$short_data"
6263         eval $LOGFE
6264 }
6265
6266 #### LINE ITEM PRINT FUNCTIONS
6267
6268 # print sound card data
6269 print_audio_data()
6270 {
6271         eval $LOGFS
6272         local i='' card_id='' audio_data='' a_audio_data='' port_data='' pci_bus_id=''
6273         local a_audio_working='' alsa_driver='' alsa_data='' port_plural='' module_version=''
6274         local bus_usb_text='' bus_usb_id='' line_starter='Audio:' alsa='' alsa_version=''
6275         # set A_AUDIO_DATA and get alsa data
6276         get_audio_data
6277         get_audio_alsa_data
6278         # alsa driver data now prints out no matter what
6279         if [[ -n $A_ALSA_DATA ]];then
6280                 IFS=","
6281                 if [[ -n ${A_ALSA_DATA[0]} ]];then
6282                         alsa=${A_ALSA_DATA[0]}
6283                 else
6284                         alsa='N/A'
6285                 fi
6286                 if [[ -n ${A_ALSA_DATA[1]} ]];then
6287                         alsa_version=${A_ALSA_DATA[1]}
6288                 else
6289                         alsa_version='N/A'
6290                 fi
6291                 alsa_data="${C1}Sound:${C2} $alsa ${C1}ver$SEP3${C2} $alsa_version"
6292                 IFS="$ORIGINAL_IFS"
6293         fi
6294         # note, error handling is done in the get function, so this will never be null, but
6295         # leaving the test just in case it's changed.
6296         if [[ -n ${A_AUDIO_DATA[@]} ]];then
6297                 for (( i=0; i< ${#A_AUDIO_DATA[@]}; i++ ))
6298                 do
6299                         IFS=","
6300                         a_audio_working=( ${A_AUDIO_DATA[i]} )
6301                         IFS="$ORIGINAL_IFS"
6302                         port_data=''
6303                         alsa_driver=''
6304                         audio_data=''
6305                         port_plural=''
6306                         module_version=''
6307                         pci_bus_id=''
6308                         bus_usb_text=''
6309                         bus_usb_id=''
6310                         if [[ ${#A_AUDIO_DATA[@]} -gt 1 ]];then
6311                                 card_id="-$(( $i + 1 ))"
6312                         fi
6313                         if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then
6314                                 module_version=$( print_module_version "${a_audio_working[3]}" 'audio' )
6315                         elif [[ -n ${a_audio_working[1]} && $B_EXTRA_DATA == 'true' ]];then
6316                                 module_version=$( print_module_version "${a_audio_working[1]}" 'audio' )
6317                         fi
6318                         # we're testing for the presence of the 2nd array item here, which is the driver name
6319                         if [[ -n ${a_audio_working[1]} ]];then
6320                                 alsa_driver=" ${C1}driver$SEP3${C2} ${a_audio_working[1]}"
6321                         fi
6322                         if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then
6323                                 if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then
6324                                         port_plural='s'
6325                                 fi
6326                                 port_data=" ${C1}port$port_plural$SEP3${C2} ${a_audio_working[2]}"
6327                         fi
6328                         if [[ -n ${a_audio_working[4]} && $B_EXTRA_DATA == 'true' ]];then
6329                                 if [[ ${a_audio_working[1]} != 'USB Audio' ]];then
6330                                         bus_usb_text='bus-ID'
6331                                 else
6332                                         bus_usb_text='usb-ID'
6333                                 fi
6334                                 bus_usb_id=${a_audio_working[4]}
6335                                 pci_bus_id=" ${C1}$bus_usb_text$SEP3${C2} $bus_usb_id"
6336                         fi
6337                         if [[ -n ${a_audio_working[0]} ]];then
6338                                 audio_data="${C1}Card$card_id:${C2} ${a_audio_working[0]}$alsa_driver$port_data$pci_bus_id"
6339                         fi
6340                         # only print alsa on last line if short enough, otherwise print on its own line
6341                         if [[ $i -eq 0 ]];then
6342                                 if [[ -n $alsa_data && $( calculate_line_length "${audio_data}$alsa_data" ) -lt $LINE_MAX ]];then
6343                                         audio_data="$audio_data $alsa_data"
6344                                         alsa_data=''
6345                                 fi
6346                         fi
6347                         if [[ -n $audio_data ]];then
6348                                 audio_data=$( create_print_line "$line_starter" "$audio_data" )
6349                                 print_screen_output "$audio_data"
6350                                 line_starter=' '
6351                         fi
6352                 done
6353         fi
6354         if [[ -n $alsa_data ]];then
6355                 alsa_data=$( sed 's/ALSA/Advanced Linux Sound Architecture/' <<< $alsa_data )
6356                 alsa_data=$( create_print_line "$line_starter" "$alsa_data" )
6357                 print_screen_output "$alsa_data"
6358         fi
6359         eval $LOGFE
6360 }
6361
6362 print_cpu_data()
6363 {
6364         eval $LOGFS
6365         local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data=''
6366         local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags=''
6367
6368         ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\""
6369         # Array A_CPU_DATA always has one extra element: max clockfreq found.
6370         # that's why its count is one more than you'd think from cores/cpus alone
6371         # load A_CPU_DATA
6372         get_cpu_data
6373
6374         IFS=","
6375         local a_cpu_working=(${A_CPU_DATA[0]})
6376         IFS="$ORIGINAL_IFS"
6377         local cpu_model="${a_cpu_working[0]}"
6378         ## assemble data for output
6379         local cpu_clock="${a_cpu_working[1]}"
6380
6381         cpu_vendor=${a_cpu_working[5]}
6382
6383         # set A_CPU_CORE_DATA
6384         get_cpu_core_count
6385         local cpc_plural='' cpu_count_print='' model_plural=''
6386         local cpu_physical_count=${A_CPU_CORE_DATA[0]}
6387         local cpu_core_count=${A_CPU_CORE_DATA[3]}
6388         local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
6389         local cpu_type=${A_CPU_CORE_DATA[2]}
6390
6391         if [[ $cpu_physical_count -gt 1 ]];then
6392                 cpc_plural='(s)'
6393                 cpu_count_print="$cpu_physical_count "
6394                 model_plural='s'
6395         fi
6396
6397         local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core"
6398         # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1
6399         # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>"
6400         # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_,
6401         # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note.
6402         # This has been confirmed by #bash on freenode.
6403         # The above mentioned only emerges when using the debugging markers below
6404         ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------"
6405
6406         if [[ -z ${a_cpu_working[2]} ]];then
6407                 a_cpu_working[2]="unknown"
6408         fi
6409
6410         cpu_data=$( create_print_line "CPU$cpc_plural:" "${C1}${cpu_data_string}${C2} ${a_cpu_working[0]}$model_plural (${cpu_type})" )
6411         if [[ $B_SHOW_CPU == 'true' ]];then
6412                 # update for multicore, bogomips x core count.
6413                 if [[ $B_EXTRA_DATA == 'true' ]];then
6414 #                       if [[ $cpu_vendor != 'intel' ]];then
6415                                 bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
6416 #                       else
6417 #                               bmip_data="${a_cpu_working[4]}"
6418 #                       fi
6419                         bmip_data=" ${C1}bmips$SEP3${C2} $bmip_data"
6420                 fi
6421                 ## note: this handles how intel reports L2, total instead of per core like AMD does
6422                 # note that we need to multiply by number of actual cpus here to get true cache size
6423                 if [[ $cpu_vendor != 'intel' ]];then
6424                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))"  )
6425                 else
6426                         cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count"  )
6427                 fi
6428                 # only print shortened list
6429                 if [[ $B_CPU_FLAGS_FULL != 'true' ]];then
6430                         cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" )
6431                         cpu_flags=" ${C1}flags$SEP3${C2} ($cpu_flags)"
6432                 fi
6433                 cpu_data="$cpu_data${C2} ${C1}cache$SEP3${C2} $cpu_cache$cpu_flags$bmip_data${CN}"
6434         fi
6435         # we don't this printing out extra line unless > 1 cpu core
6436         if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
6437                 cpu_clock_speed='' # null < verbosity level 5
6438         else
6439                 cpu_data="$cpu_data ${C1}clocked at${C2} ${a_cpu_working[1]} MHz${CN}"
6440         fi
6441
6442         cpu_data="$cpu_data $cpu_clock_speed"
6443         print_screen_output "$cpu_data"
6444
6445         # we don't this printing out extra line unless > 1 cpu core
6446         if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
6447                 for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ ))
6448                 do
6449                         IFS=","
6450                         a_cpu_working=(${A_CPU_DATA[i]})
6451                         IFS="$ORIGINAL_IFS"
6452                         # note: the first iteration will create a first space, for color code separation below
6453                         cpu_multi_clock_data="$cpu_multi_clock_data ${C1}$(( i + 1 )):${C2} ${a_cpu_working[1]} MHz${CN}"
6454                         # someone actually appeared with a 16 core system, so going to stop the cpu core throttle
6455                         # if this had some other purpose which we can't remember we'll add it back in
6456                         #if [[ $i -gt 10 ]];then
6457                         #       break
6458                         #fi
6459                 done
6460                 if [[ -n $cpu_multi_clock_data ]];then
6461                         cpu_multi_clock_data=$( create_print_line " " "${C1}Clock Speeds:${C2}$cpu_multi_clock_data" )
6462                         print_screen_output "$cpu_multi_clock_data"
6463                 fi
6464         fi
6465         if [[ $B_CPU_FLAGS_FULL == 'true' ]];then
6466                 print_cpu_flags_full "${a_cpu_working[3]}"
6467         fi
6468         eval $LOGFE
6469 }
6470
6471 # takes list of all flags, split them and prints x per line
6472 # args: $1 - cpu flag string
6473 print_cpu_flags_full()
6474 {
6475         eval $LOGFS
6476         local cpu_flags_full="$1" a_cpu_flags='' line_starter=''
6477         local i=0 counter=0 max_length=18 max_length_add=18 flag='' flag_data=''
6478
6479         # build the flag line array
6480         for flag in $cpu_flags_full
6481         do
6482                 a_cpu_flags[$counter]="${a_cpu_flags[$counter]}$flag "
6483                 if [[ $i -ge $max_length ]];then
6484                         (( counter++ ))
6485                         max_length=$(( $max_length + $max_length_add ))
6486                 fi
6487                 ((i++))
6488         done
6489         # then print it out
6490         for (( i=0; i < ${#a_cpu_flags[@]};i++ ))
6491         do
6492                 if [[ $i -eq 0 ]];then
6493                         line_starter="${C1}CPU Flags$SEP3${C2} "
6494                 else
6495                         line_starter=''
6496                 fi
6497                 flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" )
6498                 print_screen_output "$flag_data"
6499         done
6500         eval $LOGFE
6501 }
6502
6503 print_gfx_data()
6504 {
6505         eval $LOGFS
6506         local gfx_data='' i='' card_id='' root_alert='' root_x_string='' a_gfx_working=''
6507         local b_is_mesa='false' display_full_string='' gfx_bus_id='' gfx_card_data=''
6508         local res_tty='Resolution' xorg_data='' x_vendor_string='' 
6509         local spacer='' x_driver='' x_driver_string='' x_driver_plural='' direct_render_string=''
6510         local separator_loaded='' separator_unloaded='' separator_failed=''
6511         local loaded='' unloaded='' failed=''
6512         local line_starter='Graphics:'
6513         local screen_resolution="$( get_graphics_res_data )"
6514         # set A_GFX_CARD_DATA
6515         get_graphics_card_data
6516         # set A_X_DATA
6517         get_graphics_x_data
6518         local x_vendor=${A_X_DATA[0]}
6519         local x_version=${A_X_DATA[1]}
6520         # set A_GLX_DATA
6521         get_graphics_glx_data
6522         local glx_renderer="${A_GLX_DATA[0]}"
6523         local glx_version="${A_GLX_DATA[1]}"
6524         # this can contain a long No case debugging message, so it's being sliced off
6525         # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why
6526         local glx_direct_render=$( gawk '{print $1}' <<< "${A_GLX_DATA[2]}" )
6527         
6528         # set A_GRAPHIC_DRIVERS
6529         get_graphics_driver
6530         
6531         if [[ ${#A_GRAPHIC_DRIVERS[@]} -eq 0 ]];then
6532                 x_driver=' N/A'
6533         else
6534                 for (( i=0; i < ${#A_GRAPHIC_DRIVERS[@]}; i++ ))
6535                 do
6536                         IFS=","
6537                         a_gfx_working=( ${A_GRAPHIC_DRIVERS[i]} )
6538                         IFS="$ORIGINAL_IFS"
6539                         case ${a_gfx_working[1]} in
6540                                 loaded)
6541                                         loaded="$loaded$separator_loaded${a_gfx_working[0]}"
6542                                         separator_loaded=','
6543                                         ;;
6544                                 unloaded)
6545                                         unloaded="$unloaded$separator_unloaded${a_gfx_working[0]}"
6546                                         separator_unloaded=','
6547                                         ;;
6548                                 failed)
6549                                         failed="$failed$separator_failed${a_gfx_working[0]}"
6550                                         separator_failed=','
6551                                         ;;              
6552                         esac
6553                 done
6554         fi
6555         if [[ -n $loaded ]];then
6556                 x_driver="${x_driver} $loaded"
6557         fi
6558         if [[ -n $unloaded ]];then
6559                 x_driver="${x_driver} (unloaded: $unloaded)"
6560         fi
6561         if [[ -n $failed ]];then
6562                 x_driver="${x_driver} ${RED}FAILED:${C2} $failed"
6563         fi
6564
6565         if [[ ${#A_GRAPHIC_DRIVERS[@]} -gt 1 ]];then
6566                 x_driver_plural='s'
6567         fi
6568         x_driver_string="${C1}driver$x_driver_plural$SEP3${C2}$x_driver "
6569         
6570         # some basic error handling:
6571         if [[ -z $screen_resolution ]];then
6572                 screen_resolution='N/A'
6573         fi
6574         if [[ -z $x_vendor || -z $x_version ]];then
6575                 x_vendor_string="${C1}X-Vendor:${C2} N/A "
6576         else
6577                 x_vendor_string="${C1}$x_vendor$SEP3${C2} $x_version "
6578         fi
6579
6580         if [[ $B_ROOT == 'true' ]];then
6581                 root_x_string='for root '
6582                 if [[ $B_RUNNING_IN_SHELL == 'true' || $B_CONSOLE_IRC == 'true' ]];then
6583                         res_tty='tty size'
6584                 fi
6585         fi
6586         if [[ $B_RUNNING_IN_X != 'true' ]];then
6587                 root_x_string="${root_x_string}out of X"
6588                 res_tty='tty size'
6589         fi
6590         
6591         if [[ -n $root_x_string ]];then
6592                 root_x_string="${C1}Advanced Data:${C2} N/A $root_x_string"
6593         fi
6594
6595         display_full_string="$x_vendor_string$x_driver_string${C1}${res_tty}$SEP3${C2} ${screen_resolution} $root_x_string"
6596
6597         if [[ ${#A_GFX_CARD_DATA[@]} -gt 0 ]];then
6598                 for (( i=0; i < ${#A_GFX_CARD_DATA[@]}; i++ ))
6599                 do
6600                         IFS=","
6601                         a_gfx_working=( ${A_GFX_CARD_DATA[i]} )
6602                         IFS="$ORIGINAL_IFS"
6603                         gfx_bus_id=''
6604                         gfx_card_data=${a_gfx_working[0]}
6605                         if [[ $B_EXTRA_DATA == 'true' ]];then
6606                                 if [[ -n ${a_gfx_working[1]} ]];then
6607                                         gfx_bus_id=" ${C1}bus-ID$SEP3${C2} ${a_gfx_working[1]}"
6608                                 else
6609                                         gfx_bus_id=" ${C1}bus-ID$SEP3${C2} N/A"
6610                                 fi
6611                         fi
6612                         if [[ ${#A_GFX_CARD_DATA[@]} -gt 1 ]];then
6613                                 card_id="Card-$(($i+1)):"
6614                         else
6615                                 card_id='Card:'
6616                         fi
6617                         gfx_data="${C1}$card_id${C2} $gfx_card_data$gfx_bus_id "
6618                         if [[ ${#A_GFX_CARD_DATA[@]} -gt 1 ]];then
6619                                 gfx_data=$( create_print_line "$line_starter" "${gfx_data}" )
6620                                 print_screen_output "$gfx_data"
6621                                 line_starter=' '
6622                                 gfx_data=''
6623                         fi
6624                 done
6625         # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes..
6626         else
6627                 gfx_data="${C1}Card:${C2} Failed to Detect Video Card! "
6628         fi
6629         if [[ -n $gfx_data && $( calculate_line_length "${gfx_data}$display_full_string" ) -lt $LINE_MAX ]];then
6630                 gfx_data=$( create_print_line "$line_starter" "${gfx_data}$display_full_string" )
6631         else
6632                 if [[ -n $gfx_data ]];then
6633                         gfx_data=$( create_print_line "$line_starter" "$gfx_data" )
6634                         print_screen_output "$gfx_data"
6635                         line_starter=' '
6636                 fi
6637                 gfx_data=$( create_print_line "$line_starter" "$display_full_string" )
6638         fi
6639         print_screen_output "$gfx_data"
6640 #       if [[ -z $glx_renderer || -z $glx_version ]];then
6641 #               b_is_mesa='true'
6642 #       fi
6643
6644         ## note: if glx render or version have no content, then mesa is true
6645         # if [[ $B_SHOW_X_DATA == 'true' ]] && [[ $b_is_mesa != 'true' ]];then
6646         if [[ $B_SHOW_X_DATA == 'true' && $B_ROOT != 'true' ]];then
6647                 if [[ -z $glx_renderer ]];then
6648                         glx_renderer='N/A'
6649                 fi
6650                 if [[ -z $glx_version ]];then
6651                         glx_version='N/A'
6652                 fi
6653                 if [[ -z $glx_direct_render ]];then
6654                         glx_direct_render='N/A'
6655                 fi
6656                 if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then
6657                         direct_render_string=" ${C1}Direct Rendering$SEP3${C2} ${glx_direct_render}${CN}"
6658                 fi
6659                 gfx_data="${C1}GLX Renderer$SEP3${C2} ${glx_renderer} ${C1}GLX Version$SEP3${C2} ${glx_version}${CN}$direct_render_string"
6660                 gfx_data=$( create_print_line " " "$gfx_data" )
6661                 
6662                 print_screen_output "$gfx_data"
6663         fi
6664         eval $LOGFE
6665 }
6666
6667 print_hard_disk_data()
6668 {
6669         eval $LOGFS
6670         local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string=''
6671         local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name='' divisor=5
6672         local Line_Starter='Drives:' # inherited by print_optical_drives
6673
6674         # load A_HDD_DATA
6675         get_hdd_data_basic
6676         ## note: if hdd_model is declared prior to use, whatever string you want inserted will
6677         ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
6678         local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
6679         IFS=","
6680         local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
6681         IFS="$ORIGINAL_IFS"
6682         local hdd_capacity=${a_hdd_basic_working[0]}
6683         local hdd_used=${a_hdd_basic_working[1]}
6684
6685         if [[ $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
6686         ## note: the output part of this should be in the print hdd data function, not here
6687                 get_hard_drive_data_advanced
6688                 for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ ))
6689                 do
6690                         # this adds the (x) numbering in front of each disk found, and creates the full disk string
6691                         IFS=","
6692                         a_hdd_working=( ${A_HDD_DATA[i]} )
6693                         IFS="$ORIGINAL_IFS"
6694                         if [[ $B_SHOW_DISK == 'true' ]];then
6695                                 if [[ -n ${a_hdd_working[3]} ]];then
6696                                         usb_data="${a_hdd_working[3]} "
6697                                 else
6698                                         usb_data=''
6699                                 fi
6700                                 dev_data="/dev/${a_hdd_working[0]} "
6701                                 size_data=" ${a_hdd_working[1]}"
6702                                 if [[ $B_EXTRA_DATA == 'true' && -n $dev_data ]];then
6703                                         hdd_temp_data=$( get_hdd_temp_data "$dev_data" )
6704                                         # error handling is done in get data function
6705                                         if [[ -n $hdd_temp_data ]];then
6706                                                 hdd_temp_data=" ${hdd_temp_data}C"
6707                                         else
6708                                                 hdd_temp_data=''
6709                                         fi
6710                                 fi
6711                                 divisor=2 # for modulus line print out, either 2 items for full, or default for short
6712                         fi
6713                         hdd_name="${a_hdd_working[2]}"
6714                         hdd_string="$usb_data$dev_data$hdd_name$size_data$hdd_temp_data"
6715                         hdd_model="${hdd_model}${C1}$(($i+1)):${C2} $hdd_string "
6716                         # printing line one, then new lines according to $divisor setting, and after, if leftovers, print that line.
6717                         case $i in 
6718                                 0)
6719                                         hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used}) ${hdd_model}" )
6720                                         print_screen_output "$hdd_data"
6721                                         hdd_model=''
6722                                         Line_Starter=' '
6723                                         ;;
6724                                 *)
6725                                         # using modulus here, if divisible by $divisor, print line, otherwise skip
6726                                         if [[ $(( $i % $divisor )) -eq 0 ]];then
6727                                                 hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
6728                                                 print_screen_output "$hdd_data"
6729                                                 hdd_model=''
6730                                                 Line_Starter=' '
6731                                         fi
6732                                         ;;
6733                         esac
6734                 done
6735                 # then print any leftover items
6736                 if [[ -n $hdd_model ]];then
6737                         hdd_data=$( create_print_line "$Line_Starter" "${hdd_model}${CN}" )
6738                         print_screen_output "$hdd_data"
6739                 fi
6740         else
6741                 hdd_data=$( create_print_line "$Line_Starter" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})${CN}" )
6742                 print_screen_output "$hdd_data"
6743                 Line_Starter=' '
6744         fi
6745         if [[ $B_SHOW_FULL_OPTICAL == 'true' || $B_SHOW_BASIC_OPTICAL == 'true' ]];then
6746                 print_optical_drive_data
6747         fi
6748
6749         eval $LOGFE
6750 }
6751
6752 print_info_data()
6753 {
6754         eval $LOGFS
6755
6756         local info_data='' line_starter='Info:'
6757         local runlvl='' client_data=''
6758         local memory="$( get_memory_data )"
6759         local processes="$(( $( ps aux | wc -l ) - 1 ))"
6760         local up_time="$( get_uptime )"
6761         local script_patch_number=$( get_patch_version_string )
6762         local gcc_string='' gcc_installed='' gcc_others='' closing_data=''
6763         
6764         if [[ $B_EXTRA_DATA == 'true' ]];then
6765                 get_gcc_system_version
6766                 if [[ ${#A_GCC_VERSIONS[@]} -gt 0 ]];then
6767                         if [[ -n ${A_GCC_VERSIONS[0]} ]];then
6768                                 gcc_installed=${A_GCC_VERSIONS[0]}
6769                         else
6770                                 gcc_installed='N/A'
6771                         fi
6772                         if [[ $B_EXTRA_EXTRA_DATA == 'true' && -n ${A_GCC_VERSIONS[1]} ]];then
6773                                 gcc_others=" ${C1}alt$SEP3${C2} $( tr ',' '/' <<< ${A_GCC_VERSIONS[1]} )"
6774                         fi
6775                         gcc_installed="${C1}Gcc sys$SEP3${C2} $gcc_installed$gcc_others "
6776                 fi
6777         fi
6778
6779         # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch!
6780         # long_last=$( echo -ne "${C1}Processes$SEP3${C2} ${processes}${CN} | ${C1}Uptime$SEP3${C2} ${up_time}${CN} | ${C1}Memory$SEP3${C2} ${MEM}${CN}" )
6781         info_data="${C1}Processes$SEP3${C2} ${processes} ${C1}Uptime$SEP3${C2} ${up_time} ${C1}Memory$SEP3${C2} ${memory}${CN} "
6782
6783         # this only triggers if no X data is present or if extra data switch is on
6784         if [[ $B_SHOW_X_DATA != 'true' || $B_EXTRA_DATA == 'true' ]];then
6785                 runlvl="$( get_runlevel_data )"
6786                 if [[ -n $runlvl ]];then
6787                         info_data="${info_data}${C1}Runlevel$SEP3${C2} ${runlvl} "
6788                 fi
6789         fi
6790         if [[ $SHOW_IRC -gt 0 ]];then
6791                 client_data="${C1}Client$SEP3${C2} ${IRC_CLIENT}${IRC_CLIENT_VERSION} "
6792         fi
6793         info_data="${info_data}$gcc_installed"
6794         closing_data="$client_data${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$script_patch_number${CN}"
6795         if [[ -n $info_data && $( calculate_line_length "$info_data$closing_data" ) -gt $LINE_MAX ]];then
6796                 info_data=$( create_print_line "$line_starter" "$info_data" )
6797                 print_screen_output "$info_data"
6798                 info_data="$closing_data"
6799                 line_starter=' '
6800         else
6801                 info_data="${info_data}$closing_data"
6802         fi
6803         info_data=$( create_print_line "$line_starter" "$info_data" )
6804         if [[ $SCHEME -gt 0 ]];then
6805                 info_data="${info_data} ${NORMAL}"
6806         fi
6807         print_screen_output "$info_data"
6808         eval $LOGFE
6809 }
6810
6811 print_machine_data()
6812 {
6813         eval $LOGFS
6814         
6815         local system_line='' mobo_line='' bios_line='' chassis_line=''
6816         local mobo_vendor='' mobo_model='' mobo_version='' mobo_serial=''
6817         local bios_vendor='' bios_version='' bios_date=''
6818         local system_vendor='' product_name='' product_version='' product_serial='' product_uuid=''
6819         local chassis_vendor='' chassis_type='' chassis_version='' chassis_serial=''
6820         local b_skip_system='false' b_skip_chassis='false'
6821         # set A_MACHINE_DATA
6822         get_machine_data
6823
6824         IFS=','
6825         ## keys for machine data are:
6826         # 0-sys_vendor 1-product_name 2-product_version 3-product_serial 4-product_uuid 
6827         # 5-board_vendor 6-board_name 7-board_version 8-board_serial 
6828         # 9-bios_vendor 10-bios_version 11-bios_date 
6829         ## with extra data: 
6830         # 12-chassis_vendor 13-chassis_type 14-chassis_version 15-chassis_serial
6831         
6832         if [[ ${#A_MACHINE_DATA[@]} -gt 0 ]];then
6833                 # note: in some case a mobo/version will match a product name/version, do not print those
6834                 # but for laptops, or even falsely id'ed desktops with batteries, let's print it all if it matches
6835                 # there can be false id laptops if battery appears so need to make sure system is filled
6836                 if [[ -z ${A_MACHINE_DATA[0]} ]];then
6837                         b_skip_system='true'
6838                 else
6839                         if [[ $B_PORTABLE != 'true'  ]];then
6840                                 # ibm / ibm can be true; dell / quantum is false, so in other words, only do this
6841                                 # in case where the vendor is the same and the version is the same and not null, 
6842                                 # otherwise the version information is going to be different in all cases I think
6843                                 if [[ -n ${A_MACHINE_DATA[0]} && ${A_MACHINE_DATA[0]} == ${A_MACHINE_DATA[5]} ]];then
6844                                         if [[ -n ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[2]} == ${A_MACHINE_DATA[7]} ]] || \
6845                                         [[ -z ${A_MACHINE_DATA[2]} && ${A_MACHINE_DATA[1]} == ${A_MACHINE_DATA[6]} ]];then
6846                                                 b_skip_system='true'
6847                                         fi
6848                                 fi
6849                         fi
6850                 fi
6851                 # no point in showing chassis if system isn't there, it's very unlikely that would be correct
6852                 if [[ $B_EXTRA_EXTRA_DATA == 'true' && $b_skip_system != 'true' ]];then
6853                         if [[ -n ${A_MACHINE_DATA[7]} && ${A_MACHINE_DATA[14]} == ${A_MACHINE_DATA[7]} ]];then
6854                                 b_skip_chassis='true'
6855                         fi
6856                         if [[ -n ${A_MACHINE_DATA[12]} && $b_skip_chassis != 'true' ]];then
6857                                 # no need to print the vendor string again if it's the same
6858                                 if [[ ${A_MACHINE_DATA[12]} != ${A_MACHINE_DATA[0]} ]];then
6859                                         chassis_vendor=" ${A_MACHINE_DATA[12]}"
6860                                 fi
6861                                 if [[ -n ${A_MACHINE_DATA[13]} ]];then
6862                                         chassis_type=" ${C1}type$SEP3${C2} ${A_MACHINE_DATA[13]}"
6863                                 fi
6864                                 if [[ -n ${A_MACHINE_DATA[14]} ]];then
6865                                         chassis_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[14]}"
6866                                 fi
6867                                 if [[ -n ${A_MACHINE_DATA[15]} && $B_OUTPUT_FILTER != 'true' ]];then
6868                                         chassis_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[15]}"
6869                                 fi
6870                                 if [[ -n "$chassis_vendor$chassis_type$chassis_version$chassis_serial" ]];then
6871                                         chassis_line="${C1}Chassis$SEP3${C2}$chassis_vendor$chassis_type$chassis_version$chassis_serial"
6872                                 fi
6873                         fi
6874                 fi
6875                 if [[ -n ${A_MACHINE_DATA[5]} ]];then
6876                         mobo_vendor=${A_MACHINE_DATA[5]}
6877                 else
6878                         mobo_vendor='N/A'
6879                 fi
6880                 if [[ -n ${A_MACHINE_DATA[6]} ]];then
6881                         mobo_model=${A_MACHINE_DATA[6]}
6882                 else
6883                         mobo_model='N/A'
6884                 fi
6885                 if [[ -n ${A_MACHINE_DATA[7]} ]];then
6886                         mobo_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[7]}"
6887                 fi
6888                 if [[ -n ${A_MACHINE_DATA[8]} && $B_OUTPUT_FILTER != 'true' ]];then
6889                         mobo_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[8]}"
6890                 fi
6891                 if [[ -n ${A_MACHINE_DATA[9]} ]];then
6892                         bios_vendor=${A_MACHINE_DATA[9]}
6893                 else
6894                         bios_vendor='N/A'
6895                 fi
6896                 if [[ -n ${A_MACHINE_DATA[10]} ]];then
6897                         bios_version=${A_MACHINE_DATA[10]}
6898                 else
6899                         bios_version='N/A'
6900                 fi
6901                 if [[ -n ${A_MACHINE_DATA[11]} ]];then
6902                         bios_date=${A_MACHINE_DATA[11]}
6903                 else
6904                         bios_date='N/A'
6905                 fi
6906                 mobo_line="${C1}Mobo$SEP3${C2} $mobo_vendor ${C1}model$SEP3${C2} $mobo_model$mobo_version$mobo_serial"
6907                 bios_line="${C1}Bios$SEP3${C2} $bios_vendor ${C1}version$SEP3${C2} $bios_version ${C1}date$SEP3${C2} $bios_date"
6908                 if [[ $( calculate_line_length "$mobo_line$bios_line" ) -lt $LINE_MAX ]];then
6909                         mobo_line="$mobo_line $bios_line"
6910                         bios_line=''
6911                 fi
6912                 if [[ $b_skip_system == 'true' ]];then
6913                         system_line=$mobo_line
6914                         mobo_line=''
6915                 else
6916                         # this has already been tested for above so we know it's not null
6917                         system_vendor=${A_MACHINE_DATA[0]}
6918                         if [[ $B_PORTABLE == 'true' ]];then
6919                                 system_vendor="$system_vendor (portable)"
6920                         fi
6921                         if [[ -n ${A_MACHINE_DATA[1]} ]];then
6922                                 product_name=${A_MACHINE_DATA[1]}
6923                         else
6924                                 product_name='N/A'
6925                         fi
6926                         if [[ -n ${A_MACHINE_DATA[2]} ]];then
6927                                 product_version=" ${C1}version$SEP3${C2} ${A_MACHINE_DATA[2]}"
6928                         fi
6929                         if [[ -n ${A_MACHINE_DATA[3]} && $B_OUTPUT_FILTER != 'true' ]];then
6930                                 product_serial=" ${C1}serial$SEP3${C2} ${A_MACHINE_DATA[3]} "
6931                         fi
6932                         system_line="${C1}System$SEP3${C2} $system_vendor ${C1}product$SEP3${C2} $product_name$product_version$product_serial"
6933                         if [[ -n $chassis_line && $( calculate_line_length "$system_line$chassis_line" ) -lt $LINE_MAX ]];then
6934                                 system_line="$system_line $chassis_line"
6935                                 chassis_line=''
6936                         fi
6937                 fi
6938                 IFS="$ORIGINAL_IFS"
6939         else
6940                 system_line="${C2}No /sys/class/dmi machine data. Try newer kernel, or install dmidecode.${CN}"
6941         fi
6942         # patch to dump all of above if dmidecode was data source and non root user
6943         if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' || ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
6944                 if [[ ${A_MACHINE_DATA[0]} == 'dmidecode-non-root-user' ]];then
6945                         system_line="${C2}No /sys/class/dmi. Using dmidecode: you must be root to run dmidecode.${CN}"
6946                 elif [[ ${A_MACHINE_DATA[0]} == 'dmidecode-no-smbios-dmi-data' ]];then
6947                         system_line="${C2}No /sys/class/dmi. Using dmidecode: no machine data available.${CN}"
6948                 fi
6949                 mobo_line=''
6950                 bios_line=''
6951                 chassis_line=''
6952         fi
6953         system_line=$( create_print_line "Machine:" "$system_line" )
6954         print_screen_output "$system_line"
6955         if [[ -n $mobo_line ]];then
6956                 mobo_line=$( create_print_line " " "$mobo_line" )
6957                 print_screen_output "$mobo_line"
6958         fi
6959         if [[ -n $bios_line ]];then
6960                 bios_line=$( create_print_line " " "$bios_line" )
6961                 print_screen_output "$bios_line"
6962         fi
6963         if [[ -n $chassis_line ]];then
6964                 chassis_line=$( create_print_line " " "$chassis_line" )
6965                 print_screen_output "$chassis_line"
6966         fi
6967         
6968         eval $LOGFE
6969 }
6970
6971 # args: $1 - module name (could be > 1, so loop it ); $2 - audio (optional)
6972 print_module_version()
6973 {
6974         eval $LOGFS
6975         local module_versions='' module='' version='' prefix='' modules=$1
6976         
6977         # note that sound driver data tends to have upper case, but modules are lower
6978         if [[ $2 == 'audio' ]];then
6979                 if [[ -z $( grep -E '^snd' <<< $modules ) ]];then
6980                         prefix='snd_' # sound modules start with snd_
6981                 fi
6982                 modules=$( tr '[A-Z]' '[a-z]' <<< $modules )
6983                 modules=$( tr '-' '_' <<< $modules )
6984                 # special intel processing, generally no version info though
6985                 if [[ $modules == 'hda intel' ]];then
6986                         modules='hda_intel'
6987                 elif [[ $modules == 'intel ich' ]];then
6988                         modules='intel8x0'
6989                 fi
6990         fi
6991
6992         for module in $modules
6993         do
6994                 version=$( get_module_version_number "$prefix$module" )
6995                 if [[ -n $version ]];then
6996                         module_versions="$module_versions $version"
6997                 fi
6998         done
6999
7000         if [[ -n $module_versions ]];then
7001                 echo " ${C1}ver$SEP3${C2}$module_versions"
7002         fi
7003         eval $LOGFE
7004 }
7005
7006 print_networking_data()
7007 {
7008         eval $LOGFS
7009         local i='' card_id='' network_data='' a_network_working='' port_data='' driver_data=''
7010         local card_string='' port_plural='' module_version='' pci_bus_id='' bus_usb_text=''
7011         local bus_usb_id='' line_starter='Network:' card_string='' card_data=''
7012         # set A_NETWORK_DATA
7013         get_networking_data
7014
7015         # will never be null because null is handled in get_network_data, but in case we change
7016         # that leaving this test in place.
7017         if [[ -n ${A_NETWORK_DATA[@]} ]];then
7018                 for (( i=0; i < ${#A_NETWORK_DATA[@]}; i++ ))
7019                 do
7020                         IFS=","
7021                         a_network_working=( ${A_NETWORK_DATA[i]} )
7022                         IFS="$ORIGINAL_IFS"
7023                         bus_usb_id=''
7024                         bus_usb_text=''
7025                         card_data=''
7026                         card_string=''
7027                         driver_data=''
7028                         module_version=''
7029                         network_data=''
7030                         pci_bus_id=''
7031                         port_data=''
7032                         port_plural=''
7033
7034                         if [[ ${#A_NETWORK_DATA[@]} -gt 1 ]];then
7035                                 card_id="-$(( $i + 1 ))"
7036                         fi
7037                         if [[ -n ${a_network_working[1]} && $B_EXTRA_DATA == 'true' ]];then
7038                                 module_version=$( print_module_version "${a_network_working[1]}" )
7039                         fi
7040                         if [[ -n ${a_network_working[1]} ]];then
7041                                 driver_data="${C1}driver$SEP3${C2} ${a_network_working[1]}$module_version "
7042                         fi
7043                         if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then
7044                                 if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then
7045                                         port_plural='s'
7046                                 fi
7047                                 port_data="${C1}port$port_plural$SEP3${C2} ${a_network_working[2]} "
7048                         fi
7049                         if [[ -n ${a_network_working[4]} && $B_EXTRA_DATA == 'true' ]];then
7050                                 if [[ -z $( grep '^usb-' <<< ${a_network_working[4]} ) ]];then
7051                                         bus_usb_text='bus-ID'
7052                                         bus_usb_id=${a_network_working[4]}
7053                                 else
7054                                         bus_usb_text='usb-ID'
7055                                         bus_usb_id=$( cut -d '-' -f '2-4' <<< ${a_network_working[4]} )
7056                                 fi
7057                                 pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id"
7058                         fi
7059                         card_string="${C1}Card$card_id:${C2} ${a_network_working[0]} "
7060                         card_data="$driver_data$port_data$pci_bus_id"
7061                         if [[ $( calculate_line_length "$card_string$card_data" ) -gt $LINE_MAX ]];then
7062                                 network_data=$( create_print_line "$line_starter" "$card_string" )
7063                                 line_starter=' '
7064                                 card_string=''
7065                                 print_screen_output "$network_data"
7066                         fi
7067                         network_data=$( create_print_line "$line_starter" "$card_string$card_data" )
7068                         line_starter=' '
7069                         print_screen_output "$network_data"
7070                         if [[ $B_SHOW_ADVANCED_NETWORK == 'true' ]];then
7071                                 print_network_advanced_data
7072                         fi
7073                 done
7074         fi
7075         if [[ $B_SHOW_IP == 'true' ]];then
7076                 print_networking_ip_data
7077         fi
7078         eval $LOGFE
7079 }
7080
7081 print_network_advanced_data()
7082 {
7083         eval $LOGFS
7084         local network_data='' if_id='N/A' duplex='N/A' mac_id='N/A' speed='N/A' oper_state='N/A'
7085         local b_is_wifi='false' speed_string='' duplex_string=''
7086         
7087                 # first check if it's a known wifi id'ed card, if so, no print of duplex/speed
7088         if [[ -n $( grep -Esi '(wireless|wifi|wi-fi|wlan|802\.11|centrino)' <<< ${a_network_working[0]} ) ]];then
7089                 b_is_wifi='true'
7090         fi
7091         if [[ -n ${a_network_working[5]} ]];then
7092                 if_id=${a_network_working[5]}
7093         fi
7094         if [[ -n ${a_network_working[6]} ]];then
7095                 oper_state=${a_network_working[6]}
7096         fi
7097         # no print out for wifi since it doesn't have duplex/speed data availabe
7098         # note that some cards show 'unknown' for state, so only testing explicitly
7099         # for 'down' string in that to skip showing speed/duplex
7100         if [[ $b_is_wifi != 'true' && $oper_state != 'down' ]];then
7101                 if [[ -n ${a_network_working[7]} ]];then
7102                         # make sure the value is strictly numeric before appending Mbps
7103                         if [[ -n $( grep -E '^[0-9\.,]+$' <<< "${a_network_working[7]}" ) ]];then
7104                                 speed="${a_network_working[7]} Mbps"
7105                         else
7106                                 speed=${a_network_working[7]}
7107                         fi
7108                 fi
7109                 speed_string="${C1}speed$SEP3${C2} $speed "
7110                 if [[ -n ${a_network_working[8]} ]];then
7111                         duplex=${a_network_working[8]}
7112                 fi
7113                 duplex_string="${C1}duplex$SEP3${C2} $duplex "
7114         fi
7115         if [[ -n ${a_network_working[9]} ]];then
7116                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
7117                         mac_id=$FILTER_STRING
7118                 else
7119                         mac_id=${a_network_working[9]}
7120                 fi
7121         fi
7122         network_data="${C1}IF:${C2} $if_id ${C1}state$SEP3${C2} $oper_state $speed_string$duplex_string${C1}mac$SEP3${C2} $mac_id"
7123         network_data=$( create_print_line " " "$network_data" )
7124         print_screen_output "$network_data"
7125         
7126         eval $LOGFE
7127 }
7128
7129 print_networking_ip_data()
7130 {
7131         eval $LOGFS
7132         local ip=$( get_networking_wan_ip_data )
7133         local wan_ip_data='' a_interfaces_working='' interfaces='' i=''
7134         local if_id='' if_ip='' if_ipv6='' if_ipv6_string='' full_string='' if_string=''
7135         local if_id_string='' if_ip_string=''
7136         local line_max=$(( $LINE_MAX - 50 ))
7137
7138         # set A_INTERFACES_DATA
7139         get_networking_local_ip_data
7140         # first print output for wan ip line. Null is handled in the get function
7141         if [[ -z $ip ]];then
7142                 ip='N/A'
7143         else
7144                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
7145                         ip=$FILTER_STRING
7146                 fi
7147         fi
7148         wan_ip_data="${C1}WAN IP:${C2} $ip "
7149         # then create the list of local interface/ip
7150         i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1
7151         while [[ -n ${A_INTERFACES_DATA[i]} ]]
7152         do
7153                 IFS=","
7154                 a_interfaces_working=(${A_INTERFACES_DATA[i]})
7155                 IFS="$ORIGINAL_IFS"
7156                 if_id='N/A'
7157                 if_ip='N/A'
7158                 if_ipv6='N/A'
7159                 if_ipv6_string=''
7160                 if [[ -z $( grep '^Interface' <<< ${a_interfaces_working[0]} ) ]];then
7161                         if [[ -n ${a_interfaces_working[1]} ]];then
7162                                 if [[ $B_OUTPUT_FILTER == 'true' ]];then
7163                                         if_ip=$FILTER_STRING
7164                                 else
7165                                         if_ip=${a_interfaces_working[1]}
7166                                 fi
7167                         fi
7168                         if_ip_string=" ${C1}ip$SEP3${C2} $if_ip"
7169                         if [[ $B_EXTRA_DATA == 'true' ]];then
7170                                 if [[ -n ${a_interfaces_working[3]} ]];then
7171                                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
7172                                                 if_ipv6=$FILTER_STRING
7173                                         else
7174                                                 if_ipv6=${a_interfaces_working[3]}
7175                                         fi
7176                                 fi
7177                                 if_ipv6_string=" ${C1}ip-v6$SEP3${C2} $if_ipv6"
7178                         fi
7179                 fi
7180                 if [[ -n ${a_interfaces_working[0]} ]];then
7181                         if_id=${a_interfaces_working[0]}
7182                 fi
7183                 if_string="$wan_ip_data$if_string${C1}IF:${C2} $if_id$if_ip_string$if_ipv6_string "
7184                 wan_ip_data=''
7185                 if [[ $( calculate_line_length "$if_string" ) -gt $line_max ]];then
7186                         full_string=$( create_print_line " " "$if_string" )
7187                         print_screen_output "$full_string"
7188                         if_string=''
7189                 fi
7190                 ((i++))
7191         done
7192         
7193         # then print out anything not printed already
7194         if [[ -n $if_string ]];then
7195                 full_string=$( create_print_line " " "$if_string" )
7196                 print_screen_output "$full_string"
7197         fi
7198         eval $LOGFE
7199 }
7200
7201 print_optical_drive_data()
7202 {
7203         eval $LOGFS
7204         local a_drives='' drive_data='' counter='' 
7205         local drive_id='' drive_links='' vendor='' speed='' multisession='' mcn='' audio=''
7206         local dvd='' state='' rw_support='' rev='' separator='' drive_string=''
7207         get_optical_drive_data
7208         # 0 - true dev path, ie, sr0, hdc
7209         # 1 - dev links to true path
7210         # 2 - device vendor - for hdx drives, vendor model are one string from proc
7211         # 3 - device model
7212         # 4 - device rev version
7213         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 0 ]];then
7214                 for (( i=0; i < ${#A_OPTICAL_DRIVE_DATA[@]}; i++ ))
7215                 do
7216                         IFS=","
7217                         a_drives=(${A_OPTICAL_DRIVE_DATA[i]})
7218                         IFS="$ORIGINAL_IFS"
7219                         audio=''
7220                         drive_data=''
7221                         drive_id=''
7222                         drive_links=''
7223                         dvd='' 
7224                         mcn='' 
7225                         multisession='' 
7226                         rev='' 
7227                         rw_support='' 
7228                         separator=''
7229                         speed='' 
7230                         state='' 
7231                         vendor=''
7232                         if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -eq 1 && -z ${a_drives[0]} && -z ${a_drives[1]} ]];then
7233                                 drive_string="No optical drives detected."
7234                                 B_SHOW_FULL_OPTICAL='false'
7235                         else
7236                                 if [[ ${#A_OPTICAL_DRIVE_DATA[@]} -gt 1 ]];then
7237                                         counter="-$(( i + 1 ))"
7238                                 fi
7239                                 if [[ -z ${a_drives[0]} ]];then
7240                                         drive_id='N/A'
7241                                 else
7242                                         drive_id="/dev/${a_drives[0]}"
7243                                 fi
7244                                 drive_links=$( sed 's/~/,/g' <<< ${a_drives[1]} )
7245                                 if [[ -z $drive_links ]];then
7246                                         drive_links='N/A'
7247                                 fi
7248                                 if [[ -n ${a_drives[2]} ]];then
7249                                         vendor=${a_drives[2]}
7250                                         if [[ -n ${a_drives[3]} ]];then
7251                                                 vendor="$vendor ${a_drives[3]}"
7252                                         fi
7253                                 fi
7254                                 if [[ -z $vendor ]];then
7255                                         if [[ -n ${a_drives[3]} ]];then
7256                                                 vendor=${a_drives[3]}
7257                                         else
7258                                                 vendor='N/A'
7259                                         fi
7260                                 fi
7261                                 if [[ $B_EXTRA_DATA == 'true' ]];then
7262                                         if [[ -n ${a_drives[4]} ]];then
7263                                                 rev=${a_drives[4]}
7264                                         else
7265                                                 rev='N/A'
7266                                         fi
7267                                         rev=" ${C1}rev$SEP3${C2} $rev"
7268                                 fi
7269                                 drive_string="$drive_id ${C1}model$SEP3${C2} $vendor$rev ${C1}dev-links$SEP3${C2} $drive_links"
7270                         fi
7271                         drive_data="${C1}Optical${counter}:${C2} $drive_string"
7272                         drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
7273                         print_screen_output "$drive_data"
7274                         Line_Starter=' '
7275                         # 5 - speed
7276                         # 6 - multisession support
7277                         # 7 - MCN support
7278                         # 8 - audio read
7279                         # 9 - cdr
7280                         # 10 - cdrw
7281                         # 11 - dvd read
7282                         # 12 - dvdr
7283                         # 13 - dvdram
7284                         # 14 - state
7285                         if [[ $B_SHOW_FULL_OPTICAL == 'true' ]];then
7286                                 if [[ -z ${a_drives[5]} ]];then
7287                                         speed='N/A'
7288                                 else
7289                                         speed="${a_drives[5]}x"
7290                                 fi
7291                                 if [[ -z ${a_drives[8]} ]];then
7292                                         audio='N/A'
7293                                 elif [[ ${a_drives[8]} == 1 ]];then
7294                                         audio='yes'
7295                                 else
7296                                         audio='no'
7297                                 fi
7298                                 audio=" ${C1}audio$SEP3${C2} $audio"
7299                                 if [[ -z ${a_drives[6]} ]];then
7300                                         multisession='N/A'
7301                                 elif [[ ${a_drives[6]} == 1 ]];then
7302                                         multisession='yes'
7303                                 else
7304                                         multisession='no'
7305                                 fi
7306                                 multisession=" ${C1}multisession$SEP3${C2} $multisession"
7307                                 if [[ -z ${a_drives[11]} ]];then
7308                                         dvd='N/A'
7309                                 elif [[ ${a_drives[11]} == 1 ]];then
7310                                         dvd='yes'
7311                                 else
7312                                         dvd='no'
7313                                 fi
7314                                 if [[ $B_EXTRA_DATA == 'true' ]];then
7315                                         if [[ -z ${a_drives[14]} ]];then
7316                                                 state='N/A'
7317                                         else
7318                                                 state="${a_drives[14]}"
7319                                         fi
7320                                         state=" ${C1}state$SEP3${C2} $state"
7321                                 fi
7322                                 if [[ -n ${a_drives[9]} && ${a_drives[9]} == 1 ]];then
7323                                         rw_support='cd-r'
7324                                         separator=','
7325                                 fi
7326                                 if [[ -n ${a_drives[10]} && ${a_drives[10]} == 1 ]];then
7327                                         rw_support="${rw_support}${separator}cd-rw"
7328                                         separator=','
7329                                 fi
7330                                 if [[ -n ${a_drives[12]} && ${a_drives[12]} == 1 ]];then
7331                                         rw_support="${rw_support}${separator}dvd-r"
7332                                         separator=','
7333                                 fi
7334                                 if [[ -n ${a_drives[13]} && ${a_drives[13]} == 1 ]];then
7335                                         rw_support="${rw_support}${separator}dvd-ram"
7336                                         separator=','
7337                                 fi
7338                                 if [[ -z $rw_support ]];then
7339                                         rw_support='none'
7340                                 fi
7341                                 
7342                                 drive_data="${C1}Features: speed$SEP3${C2} $speed$multisession$audio ${C1}dvd$SEP3${C2} $dvd ${C1}rw$SEP3${C2} $rw_support$state"
7343                                 drive_data=$( create_print_line "$Line_Starter" "$drive_data" )
7344                                 print_screen_output "$drive_data"
7345                         fi
7346                 done
7347         else
7348                 :
7349         fi
7350         eval $LOGFE
7351 }
7352
7353 print_partition_data()
7354 {
7355         eval $LOGFS
7356         local a_partition_working='' partition_used='' partition_data=''
7357         local counter=0 i=0 a_partition_data='' line_starter='' line_max=$(( $LINE_MAX - 35 ))
7358         local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label=''
7359         local part_uuid='' full_uuid='' dev_remote='' full_fs='' line_max_label_uuid=$(( $LINE_MAX - 10 ))
7360
7361         # set A_PARTITION_DATA
7362         get_partition_data
7363
7364         for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
7365         do
7366                 IFS=","
7367                 a_partition_working=(${A_PARTITION_DATA[i]})
7368                 IFS="$ORIGINAL_IFS"
7369                 full_label=''
7370                 full_uuid=''
7371
7372                 if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then
7373                         if [[ -n ${a_partition_working[2]} ]];then
7374                                 partition_used="${C1}used$SEP3${C2} ${a_partition_working[2]} (${a_partition_working[3]}) "
7375                         else
7376                                 partition_used='' # reset partition used to null
7377                         fi
7378                         if [[ -n ${a_partition_working[5]} ]];then
7379                                 full_fs="${a_partition_working[5]}"
7380                         else
7381                                 full_fs='N/A' # reset partition used to null
7382                         fi
7383                         full_fs="${C1}fs$SEP3${C2} $full_fs "
7384
7385                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then
7386                                 if [[ -n ${a_partition_working[6]} ]];then
7387                                         if [[ -z $( grep -E '(^//|:/)' <<< ${a_partition_working[6]} ) ]];then
7388                                                 part_dev="/dev/${a_partition_working[6]}"
7389                                                 dev_remote='dev'
7390                                         else
7391                                                 part_dev="${a_partition_working[6]}"
7392                                                 dev_remote='remote'
7393                                         fi
7394                                 else
7395                                         dev_remote='dev'
7396                                         part_dev='N/A'
7397                                 fi
7398                                 full_dev="${C1}$dev_remote$SEP3${C2} $part_dev "
7399                                 if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then
7400                                         if [[ -n ${a_partition_working[7]} ]];then
7401                                                 part_label="${a_partition_working[7]}"
7402                                         else
7403                                                 part_label='N/A'
7404                                         fi
7405                                         full_label="${C1}label$SEP3${C2} $part_label "
7406                                 fi
7407                                 if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then
7408                                         if [[ -n ${a_partition_working[8]} ]];then
7409                                                 part_uuid="${a_partition_working[8]}"
7410                                         else
7411                                                 part_uuid='N/A'
7412                                         fi
7413                                         full_uuid="${C1}uuid$SEP3${C2} $part_uuid"
7414                                 fi
7415                         fi
7416                         # don't show user names in output
7417                         if [[ $B_OUTPUT_FILTER == 'true' ]];then
7418                                 partitionIdClean=$( sed -r "s|/home/([^/]+)/(.*)|/home/$FILTER_STRING/\2|" <<< ${a_partition_working[0]} )
7419                         else
7420                                 partitionIdClean=${a_partition_working[0]}
7421                         fi
7422                         id_size_fs="${C1}ID:${C2} $partitionIdClean ${C1}size$SEP3${C2} ${a_partition_working[1]} $partition_used$full_fs$full_dev"
7423                         label_uuid="$full_label$full_uuid"
7424                         # label/uuid always print one per line, so only wrap if it's very long
7425                         if [[ $B_SHOW_UUIDS == 'true' && $B_SHOW_LABELS == 'true' && $( calculate_line_length "$id_size_fs$label_uuid" ) -gt $line_max_label_uuid ]];then
7426                                 a_partition_data[$counter]="$id_size_fs"
7427                                 ((counter++))
7428                                 a_partition_data[$counter]="$label_uuid"
7429                         else
7430                                 a_partition_data[$counter]="${a_partition_data[$counter]}$id_size_fs$label_uuid"
7431                         fi
7432                         # because these lines can vary widely, using dynamic length handling here
7433                         if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]] || [[ $( calculate_line_length "${a_partition_data[$counter]}" ) -gt $line_max ]];then
7434                                 ((counter++))
7435                         fi
7436                 fi
7437         done
7438         # print out all lines, line starter on first line
7439         for (( i=0; i < ${#a_partition_data[@]};i++ ))
7440         do
7441                 if [[ $i -eq 0 ]];then
7442                         line_starter='Partition:'
7443                 else
7444                         line_starter=' '
7445                 fi
7446                 partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" )
7447                 print_screen_output "$partition_data"
7448         done
7449         
7450         eval $LOGFE
7451 }
7452
7453 print_ps_data()
7454 {
7455         eval $LOGFS
7456         
7457         local b_print_first='true' 
7458
7459         if [[ $B_SHOW_PS_CPU_DATA == 'true' ]];then
7460                 get_ps_data 'cpu'
7461                 print_ps_item 'cpu' "$b_print_first"
7462                 b_print_first='false' 
7463         fi
7464         if [[ $B_SHOW_PS_MEM_DATA == 'true' ]];then
7465                 get_ps_data 'mem'
7466                 print_ps_item 'mem' "$b_print_first"
7467         fi
7468         
7469         eval $LOGFE
7470 }
7471
7472 # args: $1 - cpu/mem; $2 true/false
7473 print_ps_item()
7474 {
7475         eval $LOGFS
7476         local a_ps_data='' ps_data='' line_starter='' line_start_data='' full_line=''
7477         local app_name='' app_pid='' app_cpu='' app_mem='' throttled='' app_daemon=''
7478         local b_print_first=$2 line_counter=0 i=0 count_nu='' extra_data=''
7479         
7480         if [[ -n $PS_THROTTLED ]];then
7481                 throttled=" ${C1} - throttled from${C2} $PS_THROTTLED"
7482         fi
7483         case $1 in
7484                 cpu)
7485                         line_start_data="${C1}CPU - % used - top ${C2} $PS_COUNT ${C1}active$throttled "
7486                         ;;
7487                 mem)
7488                         line_start_data="${C1}Memory - MB / % used - top ${C2} $PS_COUNT ${C1}active$throttled"
7489                         ;;
7490         esac
7491         
7492         if [[ $b_print_first == 'true' ]];then
7493                 line_starter='Processes:'
7494         else
7495                 line_starter=' '
7496         fi
7497         
7498         # appName, appPath, appStarterName, appStarterPath, cpu, mem, pid, vsz, user
7499         ps_data=$( create_print_line "$line_starter" "$line_start_data" )
7500         print_screen_output "$ps_data"
7501
7502         for (( i=0; i < ${#A_PS_DATA[@]}; i++ ))
7503         do
7504                 IFS=","
7505                 a_ps_data=(${A_PS_DATA[i]})
7506                 IFS="$ORIGINAL_IFS"
7507                 
7508                 # handle the converted app names, with ~..~ means it didn't have a path
7509                 if [[ -n $( grep -E '^~.*~$' <<<  ${a_ps_data[0]} ) ]];then
7510                         app_daemon='daemon'
7511                 else
7512                         app_daemon='command'
7513                 fi
7514
7515                 app_name=" ${C1}$app_daemon$SEP3${C2} ${a_ps_data[0]}"
7516                 if [[ ${a_ps_data[0]} != ${a_ps_data[2]} ]];then
7517                         app_name="$app_name ${C1}(started by$SEP3${C2} ${a_ps_data[2]}${C1})${C2}"
7518                 fi
7519                 app_pid=" ${C1}pid$SEP3${C2} ${a_ps_data[6]}"
7520                 #  ${C1}user:${C2} ${a_ps_data[8]}
7521                 case $1 in
7522                         cpu)
7523                                 app_cpu=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
7524                                 if [[ $B_EXTRA_DATA == 'true' ]];then
7525                                         extra_data=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
7526                                 fi
7527                                 ;;
7528                         mem)
7529                                 app_mem=" ${C1}mem$SEP3${C2} ${a_ps_data[7]}MB (${a_ps_data[5]}%)${C2}"
7530                                 if [[ $B_EXTRA_DATA == 'true' ]];then
7531                                         extra_data=" ${C1}cpu$SEP3${C2} ${a_ps_data[4]}%"
7532                                 fi
7533                                 ;;
7534                 esac
7535                 (( line_counter++ ))
7536                 count_nu="${C1}$line_counter:${C2}"
7537                 full_line="$count_nu$app_cpu$app_mem$app_name$app_pid$extra_data"
7538                 ps_data=$( create_print_line " " "$full_line" )
7539                 print_screen_output "$ps_data"
7540         done
7541         
7542         eval $LOGFE
7543 }
7544
7545
7546 # currently only apt using distros support this feature, but over time we can add others
7547 print_repo_data()
7548 {
7549         eval $LOGFS
7550         local repo_count=0 repo_line='' file_name='' file_content='' file_name_holder=''
7551         local repo_full='' b_print_next_line='false' 
7552         
7553         get_repo_data
7554         
7555         if [[ -n $REPO_DATA ]];then
7556                 # loop through the variable's lines one by one, update counter each iteration
7557                 while read repo_line
7558                 do
7559                         (( repo_count++ ))
7560                         file_name=$( cut -d ':' -f 1 <<< $repo_line )
7561                         file_content=$( cut -d ':' -f 2-6 <<< $repo_line )
7562                         # this will dump unwanted white space line starters. Some irc channels
7563                         # use bots that show page title for urls, so need to break the url by adding 
7564                         # a white space.
7565                         if [[ $B_RUNNING_IN_SHELL != 'true' ]];then
7566                                 file_content=$( echo $file_content | sed 's|://|: //|' )
7567                         else
7568                                 file_content=$( echo $file_content )
7569                         fi
7570                         # check file name, if different, update the holder for print out
7571                         if [[ $file_name != $file_name_holder ]];then
7572                                 if [[ $REPO_FILE_ID != 'pisi repo' ]];then
7573                                         repo_full="${C1}Active $REPO_FILE_ID in file:${C2} $file_name"
7574                                 else
7575                                         repo_full="${C1}$REPO_FILE_ID:${C2} $file_name"
7576                                 fi
7577                                 file_name_holder=$file_name
7578                                 b_print_next_line='true'
7579                         else
7580                                 repo_full=$file_content
7581                         fi
7582                         # first line print Repos: 
7583                         if [[ $repo_count -eq 1 ]];then
7584                                 repo_full=$( create_print_line "Repos:" "$repo_full" )
7585                         else
7586                                 repo_full=$( create_print_line " " "$repo_full" )
7587                         fi
7588                         print_screen_output "$repo_full"
7589                         # this prints the content of the file as well as the file name
7590                         if [[ $b_print_next_line == 'true' ]];then
7591                                 repo_full=$( create_print_line " " "$file_content" )
7592                                 print_screen_output "$repo_full"
7593                                 b_print_next_line='false'
7594                         fi
7595                 done <<< "$REPO_DATA"
7596         else
7597                 repo_full=$( create_print_line "Repos:" "${C1}Error:${C2} $SCRIPT_NAME does not support this feature for your distro yet." )
7598                 print_screen_output "$repo_full"
7599         fi
7600         eval $LOGFE
7601 }
7602
7603 print_script_version()
7604 {
7605         local script_patch_number=$( get_patch_version_string )
7606         local script_version="${C1}$SCRIPT_NAME$SEP3${C2} $SCRIPT_VERSION_NUMBER$script_patch_number${CN}"
7607         # great trick from: http://ideatrash.net/2011/01/bash-string-padding-with-sed.html
7608         # left pad: sed -e :a -e 's/^.\{1,80\}$/& /;ta'
7609         # right pad: sed -e :a -e 's/^.\{1,80\}$/ &/;ta'
7610         # center pad: sed -e :a -e 's/^.\{1,80\}$/ & /;ta'
7611         #local line_max=$(( $LINE_MAX - 10 ))
7612         #script_version="$( sed -e :a -e "s/^.\{1,$line_max\}$/ &/;ta" <<< $script_version )" # use to create padding if needed
7613         # script_version=$( create_print_line "Version:" "$script_version" )
7614         print_screen_output "$script_version"
7615 }
7616
7617 print_sensors_data()
7618 {
7619         eval $LOGFS
7620         local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' 
7621         local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp=''
7622         local a_sensors_working=''
7623         local Sensors_Data="$( get_sensors_output )"
7624         get_sensors_data
7625         
7626         IFS=","
7627         a_sensors_working=( ${A_SENSORS_DATA[0]} )
7628         IFS="$ORIGINAL_IFS"
7629         # initial error cases, for missing app or unconfigured sensors. Note that array 0
7630         # always has at least 3 items, cpu/mobo/psu temp in it. If it's a single item, then
7631         # it's an error message, not the real data arrays.
7632         if [[ ${#a_sensors_working[@]} -eq 1 ]];then
7633                 cpu_temp="${C1}Error:${C2} ${A_SENSORS_DATA[0]}"
7634                 b_is_error='true'
7635         else
7636                 for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ ))
7637                 do
7638                         IFS=","
7639                         a_sensors_working=( ${A_SENSORS_DATA[i]} )
7640                         IFS="$ORIGINAL_IFS"
7641                         case $i in
7642                                 # first the temp data
7643                                 0)
7644                                         if [[ -n ${a_sensors_working[0]} ]];then
7645                                                 cpu_temp=${a_sensors_working[0]}
7646                                         else
7647                                                 cpu_temp='N/A'
7648                                         fi
7649                                         cpu_temp="${C1}System Temperatures: cpu$SEP3${C2} $cpu_temp "
7650
7651                                         if [[ -n ${a_sensors_working[1]} ]];then
7652                                                 mobo_temp=${a_sensors_working[1]}
7653                                         else
7654                                                 mobo_temp='N/A'
7655                                         fi
7656                                         mobo_temp="${C1}mobo$SEP3${C2} $mobo_temp "
7657
7658                                         if [[ -n ${a_sensors_working[2]} ]];then
7659                                                 psu_temp="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
7660                                         fi
7661                                         gpu_temp=$( get_gpu_temp_data )
7662                                         # dump the unneeded screen data for single gpu systems 
7663                                         if [[ $( wc -w <<< $gpu_temp ) -eq 1 && $B_EXTRA_DATA != 'true' ]];then
7664                                                 gpu_temp=$( cut -d ':' -f 2 <<< $gpu_temp )
7665                                         fi
7666                                         if [[ -n $gpu_temp ]];then
7667                                                 gpu_temp="${C1}gpu$SEP3${C2} ${gpu_temp} "
7668                                         fi
7669                                         ;;
7670                                 # then the fan data from main fan array
7671                                 1)
7672                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
7673                                         do
7674                                                 case $j in
7675                                                         0)
7676                                                                 # we need to make sure it's either cpu fan OR cpu fan and sys fan 1
7677                                                                 if [[ -n ${a_sensors_working[0]} ]];then
7678                                                                         cpu_fan="${a_sensors_working[0]}"
7679                                                                 elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then
7680                                                                         cpu_fan="${a_sensors_working[1]}"
7681                                                                 else
7682                                                                         cpu_fan='N/A'
7683                                                                 fi
7684                                                                 cpu_fan="${C1}Fan Speeds (in rpm): cpu$SEP3${C2} $cpu_fan "
7685                                                                 (( fan_count++ ))
7686                                                                 ;;
7687                                                         1)
7688                                                                 if [[ -n ${a_sensors_working[1]} ]];then
7689                                                                         mobo_fan="${C1}mobo$SEP3${C2} ${a_sensors_working[1]} "
7690                                                                         (( fan_count++ ))
7691                                                                 fi
7692                                                                 ;;
7693                                                         2)
7694                                                                 if [[ -n ${a_sensors_working[2]} ]];then
7695                                                                         ps_fan="${C1}psu$SEP3${C2} ${a_sensors_working[2]} "
7696                                                                         (( fan_count++ ))
7697                                                                 fi
7698                                                                 ;;
7699                                                         [3-9]|[1-9][0-9])
7700                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
7701                                                                         fan_number=$(( $j - 2 )) # sys fans start on array key 5
7702                                                                         # wrap after fan 6 total
7703                                                                         if [[ $fan_count -lt 7 ]];then
7704                                                                                 sys_fans="$sys_fans${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
7705                                                                         else
7706                                                                                 sys_fans2="$sys_fans2${C1}sys-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
7707                                                                         fi
7708                                                                         (( fan_count++ ))
7709                                                                 fi
7710                                                                 ;;
7711                                                 esac
7712                                         done
7713                                         ;;
7714                                 2)
7715                                         for (( j=0; j < ${#a_sensors_working[@]}; j++ ))
7716                                         do
7717                                                 case $j in
7718                                                         [0-9]|[1-9][0-9])
7719                                                                 if [[ -n ${a_sensors_working[$j]} ]];then
7720                                                                         fan_number=$(( $j + 1 )) # sys fans start on array key 5
7721                                                                         # wrap after fan 6 total
7722                                                                         if [[ $fan_count -lt 7 ]];then
7723                                                                                 sys_fans="$sys_fans${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
7724                                                                         else
7725                                                                                 sys_fans2="$sys_fans2${C1}fan-$fan_number$SEP3${C2} ${a_sensors_working[$j]} "
7726                                                                         fi
7727                                                                         (( fan_count++ ))
7728                                                                 fi
7729                                                                 ;;
7730                                                 esac
7731                                         done
7732                                         ;;
7733                         esac
7734                 done
7735         fi
7736         # turning off all output for case where no sensors detected or no sensors output 
7737         # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used
7738         if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then
7739                 temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp"
7740                 temp_data=$( create_print_line "Sensors:" "$temp_data" )
7741                 print_screen_output "$temp_data"
7742                 # don't print second or subsequent lines if error data
7743                 fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans"
7744                 if [[ $b_is_error != 'true' && -n $fan_data ]];then
7745                         fan_data=$( create_print_line " " "$fan_data" )
7746                         print_screen_output "$fan_data"
7747                         # and then second wrapped fan line if needed
7748                         if [[ -n $sys_fans2 ]];then
7749                                 fan_data2=$( create_print_line " " "$sys_fans2" )
7750                                 print_screen_output "$fan_data2"
7751                         fi
7752                 fi
7753         fi
7754         eval $LOGFE
7755 }
7756
7757 print_system_data()
7758 {
7759         eval $LOGFS
7760         local system_data='' bits='' desktop_environment='' 
7761         local host_kernel_string='' de_distro_string='' host_string='' desktop_type='Desktop'
7762         local host_name=$HOSTNAME
7763         local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' )
7764         local distro="$( get_distro_data )"
7765         local tty_session=$( basename "$( tty 2>/dev/null )" | sed 's/[^0-9]*//g' )
7766         
7767         # I think these will work, maybe, if logged in as root and in X
7768         if [[ $B_RUNNING_IN_X == 'true' ]];then
7769                 desktop_environment=$( get_desktop_environment )
7770                 if [[ -z $desktop_environment ]];then
7771                         desktop_environment='N/A'
7772                 fi
7773         else
7774                 if [[ -z $tty_session && $B_CONSOLE_IRC == 'true' ]];then
7775                         tty_session=$( get_console_irc_tty )
7776                 fi
7777                 if [[ -n $tty_session ]];then
7778                         tty_session=" $tty_session"
7779                 fi
7780                 desktop_environment="tty$tty_session"
7781                 desktop_type='Console'
7782         fi
7783         de_distro_string="${C1}$desktop_type$SEP3${C2} $desktop_environment ${C1}Distro$SEP3${C2} $distro"
7784         if [[ $B_EXTRA_DATA == 'true' ]];then
7785                 gcc_string=$( get_gcc_kernel_version )
7786                 if [[ -n $gcc_string ]];then
7787                         gcc_string=", ${C1}gcc$SEP3${C2} $gcc_string"
7788                 fi
7789         fi
7790         # check for 64 bit first
7791         if [[ -n $( uname -m | grep -o 'x86_64' ) ]];then
7792                 bits="64"
7793         else
7794                 bits="32"
7795         fi
7796         bits=" (${bits} bit${gcc_string})"
7797         if [[ $B_SHOW_HOST == 'true' ]];then
7798                 if [[ -z $HOSTNAME ]];then
7799                         if [[ -n $( type p hostname ) ]];then
7800                                 host_name=$( hostname )
7801                         fi
7802                         if [[ -z $host_name ]];then
7803                                 host_name='N/A'
7804                         fi
7805                 fi
7806                 host_string="${C1}Host$SEP3${C2} $host_name "
7807                 system_data=$( create_print_line "System:" "$host_string$host_name ${C1}Kernel$SEP3${C2}" )
7808         fi
7809         host_kernel_string="$host_string${C1}Kernel$SEP3${C2} $current_kernel$bits "
7810         if [[ $( calculate_line_length "$host_kernel_string$de_distro_string" ) -lt $LINE_MAX ]];then
7811                 system_data="$host_kernel_string$de_distro_string"
7812                 system_data=$( create_print_line "System:" "$system_data" )
7813         else
7814                 system_data=$( create_print_line "System:" "$host_kernel_string" )
7815                 print_screen_output "$system_data"
7816                 system_data=$( create_print_line " " "$de_distro_string" )
7817         fi
7818         print_screen_output "$system_data"
7819         eval $LOGFE
7820 }
7821
7822 print_unmounted_partition_data()
7823 {
7824         eval $LOGFS
7825         local a_unmounted_data='' line_starter='' unmounted_data='' full_fs=''
7826         local full_dev='' full_size='' full_label='' full_uuid='' full_string=''
7827         
7828         if [[ -z ${A_PARTITION_DATA} ]];then
7829                 get_partition_data
7830         fi
7831         get_unmounted_partition_data
7832         
7833         if [[ ${#A_UNMOUNTED_PARTITION_DATA[@]} -ge 1 ]];then
7834                 for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
7835                 do
7836                         IFS=","
7837                         a_unmounted_data=(${A_UNMOUNTED_PARTITION_DATA[i]})
7838                         IFS="$ORIGINAL_IFS"
7839                         if [[ -z ${a_unmounted_data[0]} ]];then
7840                                 full_dev='N/A'
7841                         else
7842                                 full_dev="/dev/${a_unmounted_data[0]}"
7843                         fi
7844                         full_dev="${C1}ID:${C2} $full_dev"
7845                         if [[ -z ${a_unmounted_data[1]} ]];then
7846                                 full_size='N/A'
7847                         else
7848                                 full_size=${a_unmounted_data[1]}
7849                         fi
7850                         full_size="${C1}size$SEP3${C2} $full_size"
7851                         if [[ -z ${a_unmounted_data[2]} ]];then
7852                                 full_label='N/A'
7853                         else
7854                                 full_label=${a_unmounted_data[2]}
7855                         fi
7856                         full_label="${C1}label$SEP3${C2} $full_label"
7857                         if [[ -z ${a_unmounted_data[3]} ]];then
7858                                 full_uuid='N/A'
7859                         else
7860                                 full_uuid=${a_unmounted_data[3]}
7861                         fi
7862                         full_uuid="${C1}uuid$SEP3${C2} $full_uuid"
7863                         if [[ -z ${a_unmounted_data[4]} ]];then
7864                                 full_fs=''
7865                         else
7866                                 full_fs="${C1}fs$SEP3${C2} ${a_unmounted_data[4]}"
7867                         fi
7868                         full_string="$full_dev $full_size $full_label $full_uuid $full_fs"
7869                         if [[ $i -eq 0 ]];then
7870                                 line_starter='Unmounted:'
7871                         else
7872                                 line_starter=' '
7873                         fi
7874                         unmounted_data=$( create_print_line "$line_starter" "$full_string" )
7875                         print_screen_output "$unmounted_data"
7876                 done
7877         else
7878                 unmounted_data=$( create_print_line "Unmounted:" "No unmounted partitions detected." )
7879                 print_screen_output "$unmounted_data"
7880         fi
7881         
7882         eval $LOGFE
7883 }
7884
7885 ########################################################################
7886 #### SCRIPT EXECUTION
7887 ########################################################################
7888
7889 main $@ ## From the End comes the Beginning
7890
7891 ## note: this EOF is needed for smxi handling, this is what triggers the full download ok
7892 ###**EOF**###