+get_pciconf_data()
+{
+ eval $LOGFS
+
+ local pciconf_data='' temp_array=''
+
+ if [[ $B_PCICONF == 'true' ]];then
+ pciconf_data="$( pciconf -lv 2>/dev/null )"
+ if [[ -n $pciconf_data ]];then
+ pciconf_data=$( gawk '
+ BEGIN {
+ IGNORECASE=1
+ }
+ {
+ gsub(/'"$BAN_LIST_NORMAL"'/, "", $0)
+ gsub(/[[:space:]]+=[[:space:]]+/, "=",$0)
+ gsub(/^[[:space:]]+|'"'"'|\"|,/, "", $0)
+ gsub(/=0x/,"=",$0)
+ # line=gensub(/.*[[:space:]]+(class=[^[:space:]]*|card=[^[:space:]]*)|chip=[^[:space:]]*|rev=[^[:space:]]*|hdr=[^[:space:]]*).*/,"\n\\1","g",$0)
+ line=gensub(/(.*@.*)/,"\n\\1",$0)
+ print line
+ }' <<< "$pciconf_data" )
+ # create empty last line with this spacing trick
+ pciconf_data="$pciconf_data
+
+EOF"
+ # echo "$pciconf_data"
+ # now insert into arrays
+ IFS=$'\n'
+ A_PCICONF_DATA=( $( gawk '
+ BEGIN {
+ fullLine=""
+ driver=""
+ vendor=""
+ device=""
+ class=""
+ chipId=""
+ pciId=""
+ itemData=""
+ IGNORECASE=1
+ }
+ /^.*@/ {
+ pciId=""
+ vendor=""
+ class=""
+ driver=""
+ device=""
+ chipId=""
+ itemData=$1
+
+ driver=gensub(/^([^@]+)@.*/, "\\1", itemData )
+ pciId=gensub(/^.*@pci([0-9\.:]+).*/, "\\1", itemData )
+ sub(/:$/, "", pciId)
+ itemData=$4
+ chipId=gensub(/.*chip=([0-9a-f][0-9a-f][0-9a-f][0-9a-f])([0-9a-f][0-9a-f][0-9a-f][0-9a-f]).*/, "\\2:\\1", itemData )
+ if ( $2 == "class=020000" ) {
+ class="network"
+ }
+ else if ( $2 == "class=030000" ) {
+ class="display"
+ }
+ else if ( $2 == "class=040300" ) {
+ class="audio"
+ }
+
+ while ( getline && $1 !~ /^$/ ) {
+ if ( $1 ~ /^vendor/ ) {
+ sub(/^vendor=/, "", $1 )
+ vendor=$0
+ }
+ else if ( $1 ~ /^device/ ) {
+ sub(/^device=/, "", $1 )
+ device=$0
+ }
+ else if ( $1 ~ /^class=/ && class == "" ) {
+ sub(/^class=/, "", $1)
+ class=$0
+ }
+ }
+ if ( device == "" ) {
+ device=vendor
+ }
+
+ fullLine=class "," device "," vendor "," driver "," pciId "," chipId
+ print fullLine
+
+ }' <<< "$pciconf_data" ))
+ IFS="$ORIGINAL_IFS"
+ fi
+ else
+ A_PCICONF_DATA='pciconf-not-installed'
+ fi
+ B_PCICONF_SET='true'
+ temp_array=${A_PCICONF_DATA[@]}
+ log_function_data "$temp_array"
+ log_function_data "$pciconf_data"
+ eval $LOGFE
+}
+
+# packs standard card arrays using the pciconf stuff
+# args: $1 - audio/network/display - matches first item in A_PCICONF_DATA arrays
+get_pciconf_card_data()
+{
+ eval $LOGFS
+ local a_temp='' array_string='' j=0 device_string=''
+ local ip_tool_command=$( type -p ifconfig )
+ local mac='' state='' speed='' duplex='' network_string=''
+
+ for (( i=0;i<${#A_PCICONF_DATA[@]};i++ ))
+ do
+ IFS=','
+ a_temp=( ${A_PCICONF_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+
+ if [[ ${a_temp[0]} == $1 ]];then
+ # don't print the vendor if it's already in the device name
+ if [[ -z $( grep -i "${a_temp[2]}" <<< "${a_temp[1]}" ) ]];then
+ device_string="${a_temp[2]} ${a_temp[1]}"
+ else
+ device_string=${a_temp[1]}
+ fi
+ case $1 in
+ audio)
+ array_string="$device_string,${a_temp[3]},,,${a_temp[4]},,${a_temp[5]}"
+ A_AUDIO_DATA[j]=$array_string
+ ;;
+ display)
+ array_string="$device_string,${a_temp[4]},${a_temp[5]}"
+ A_GRAPHICS_CARD_DATA[j]=$array_string
+ ;;
+ network)
+ if [[ -n $ip_tool_command && -n ${a_temp[3]} ]];then
+ network_string=$( $ip_tool_command ${a_temp[3]} | gawk '
+ BEGIN {
+ IGNORECASE=1
+ mac=""
+ state=""
+ speed=""
+ duplex=""
+ }
+ /^[[:space:]]*ether/ {
+ mac = $2
+ }
+ /^[[:space:]]*media/ {
+ if ( $0 ~ /<.*>/ ) {
+ duplex=gensub(/.*<([^>]+)>.*/,"\\1",$0)
+ }
+ if ( $0 ~ /\(.*\)/ ) {
+ speed=gensub(/.*\(([^<[:space:]]+).*\).*/,"\\1",$0)
+ }
+ }
+ /^[[:space:]]*status/ {
+ sub(/.*status[:]?[[:space:]]*/,"", $0)
+ state=$0
+ }
+ END {
+ print state "~" speed "~" mac "~" duplex
+ }')
+ fi
+ if [[ -n $network_string ]];then
+ mac=$( cut -d '~' -f 3 <<< $network_string )
+ state=$( cut -d '~' -f 1 <<< $network_string )
+ speed=$( cut -d '~' -f 2 <<< $network_string )
+ duplex=$( cut -d '~' -f 4 <<< $network_string )
+ fi
+ array_string="$device_string,${a_temp[3]},,,${a_temp[4]},${a_temp[3]},$state,$speed,$duplex,$mac,${a_temp[5]}"
+ A_NETWORK_DATA[j]=$array_string
+ ;;
+ esac
+ ((j++))
+ fi
+ done
+
+ eval $LOGFE
+}
+
+# args: $1 - type cpu/mem
+get_ps_tcm_data()
+{
+ eval $LOGFS
+ local array_length='' reorder_temp='' i=0 head_tail='' sort_type='' ps_data=''
+
+ # bummer, have to make it more complex here because of reverse sort
+ # orders in output, pesky lack of support of +rss in old systems
+ case $1 in
+ mem)
+ if [[ $BSD_TYPE != 'bsd' ]];then
+ sort_type='ps aux --sort -rss'
+ head_tail='head'
+ else
+ sort_type='ps aux -m'
+ head_tail='head'
+ fi
+ ;;
+ cpu)
+ if [[ $BSD_TYPE != 'bsd' ]];then
+ sort_type='ps aux --sort %cpu'
+ head_tail='tail'
+ else
+ sort_type='ps aux -r'
+ head_tail='head'
+ fi
+ ;;
+ esac
+
+ # throttle potential irc abuse
+ if [[ $B_RUNNING_IN_SHELL != 'true' && $PS_COUNT -gt 5 ]];then
+ PS_THROTTLED=$PS_COUNT
+ PS_COUNT=5
+ fi
+ # use eval here to avoid glitches with -
+ ps_data="$( eval $sort_type )"
+
+ IFS=$'\n'
+ # note that inxi can use a lot of cpu, and can actually show up here as the script runs
+ A_PS_DATA=( $( echo "$ps_data" | grep -Ev "($SCRIPT_NAME|%CPU|[[:space:]]ps[[:space:]])" | $head_tail -n $PS_COUNT | gawk '
+ BEGIN {
+ IGNORECASE=1
+ appName=""
+ appPath=""
+ appStarterName=""
+ appStarterPath=""
+ cpu=""
+ mem=""
+ pid=""
+ user=""
+ rss=""
+ }
+ {
+ cpu=$3
+ mem=$4
+ pid=$2
+ user=$1
+ rss=sprintf( "%.2f", $6/1024 )
+ # have to get rid of [,],(,) eg: [lockd] which break the printout function compare in bash
+ gsub(/\[|\]|\(|\)/,"~", $0 )
+ if ( $12 ~ /^\// ){
+ appStarterPath=$11
+ appPath=$12
+ }
+ else {
+ appStarterPath=$11
+ appPath=$11
+ }
+ appStarterName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appStarterPath )
+ appName=gensub( /(\/.*\/)(.*)/, "\\2", "1", appPath )
+ print appName "," appPath "," appStarterName "," appStarterPath "," cpu "," mem "," pid "," rss "," user
+ }
+ ' ) )
+ # make the array ordered highest to lowest so output looks the way we expect it to
+ # this isn't necessary for -rss, and we can't make %cpu ordered the other way, so
+ # need to reverse it here. -rss is used because on older systems +rss is not supported
+ if [[ $1 == 'cpu' && $BSD_TYPE != 'bsd' ]];then
+ array_length=${#A_PS_DATA[@]};
+ while (( $i < $array_length/2 ))
+ do
+ reorder_temp=${A_PS_DATA[i]}f
+ A_PS_DATA[i]=${A_PS_DATA[$array_length-$i-1]}
+ A_PS_DATA[$array_length-$i-1]=$reorder_temp
+ (( i++ ))
+ done
+ fi
+
+ IFS="$ORIGINAL_IFS"
+
+# echo ${A_PS_DATA[@]}
+ eval $LOGFE
+}
+
+# mdstat syntax information: http://www-01.ibm.com/support/docview.wss?uid=isg3T1011259
+# note that this does NOT use either Disk or Partition information for now, ie, there
+# is no connection between the data types, but the output should still be consistent
+get_raid_data()
+{
+ eval $LOGFS
+
+ local mdstat=''
+
+ if [[ $B_MDSTAT_FILE == 'true' ]];then
+ mdstat="$( cat $FILE_MDSTAT 2>/dev/null )"
+ fi
+
+ if [[ -n $mdstat ]];then
+ # need to make sure there's always a newline in front of each record type, and
+ # also correct possible weird formats for the output from older kernels etc.
+ mdstat="$( sed -e 's/^md/\nmd/' -e 's/^unused[[:space:]]/\nunused /' \
+ -e 's/read_ahead/\nread_ahead/' -e 's/^resync=/\nresync=/' -e 's/^Event/\nEvent/' \
+ -e 's/^[[:space:]]*$//' -e 's/[[:space:]]read_ahead/\nread_ahead/' <<< "$mdstat" )"
+ # some fringe cases do not end as expected, so need to add newlines plus EOF to make sure while loop doesn't spin
+ mdstat=$( echo -e "$mdstat\n\nEOF" )
+
+ IFS=$'\n'
+ A_RAID_DATA=( $(
+ gawk '
+ BEGIN {
+ IGNORECASE=1
+ RS="\n"
+ }
+
+ /^personalities/ {
+ KernelRaidSupport = gensub(/personalities[[:space:]]*:[[:space:]]*(.*)/, "\\1", 1, $0)
+ # clean off the brackets
+ gsub(/[\[\]]/,"",KernelRaidSupport)
+ print "KernelRaidSupport," KernelRaidSupport
+ }
+ /^read_ahead/ {
+ ReadAhead=gensub(/read_ahead (.*)/, "\\1", 1 )
+ print "ReadAhead," ReadAhead
+ }
+ /^Event:/ {
+ print "raidEvent," $NF
+ }
+ # print logic will search for this value and use it to print out the unused devices data
+ /^unused devices/ {
+ unusedDevices = gensub(/^unused devices:[[:space:]][<]?([^>]*)[>]?.*/, "\\1", 1, $0)
+ print "UnusedDevices," unusedDevices
+ }
+
+ /^md/ {
+ # reset for each record loop through
+ deviceState = ""
+ bitmapValues = ""
+ blocks = ""
+ chunkSize = ""
+ components = ""
+ device = ""
+ deviceReport = ""
+ finishTime = ""
+ recoverSpeed = ""
+ recoveryProgressBar = ""
+ recoveryPercent = ""
+ raidLevel = ""
+ sectorsRecovered = ""
+ separator = ""
+ superBlock = ""
+ uData = ""
+
+ while ( !/^[[:space:]]*$/ ) {
+ gsub(/,/, " ", $0 )
+ gsub(/[[:space:]]+/, " ", $0 )
+ if ( $0 ~ /^md/ ) {
+ device = gensub(/(md.*)[[:space:]]?:/, "\\1", "1", $1 )
+ }
+ if ( $0 ~ /mirror|raid[0-9]+/ ) {
+ raidLevel = gensub(/(.*)raid([0-9]+)(.*)/, "\\2", "g", $0 )
+ }
+ if ( $0 ~ /(active \(auto-read-only\)|active|inactive)/ ) {
+ deviceState = gensub(/(.*) (active \(auto-read-only\)|active|inactive) (.*)/, "\\2", "1", $0 )
+ }
+ # gawk will not return all the components using gensub, only last one
+ separator = ""
+ for ( i=3; i<=NF; i++ ) {
+ if ( $i ~ /[hs]d[a-z][0-9]*(\[[0-9]+\])?(\([SF]\))?/ ) {
+ components = components separator $i
+ separator=" "
+ }
+ }
+ if ( $0 ~ /blocks/ ) {
+ blocks = gensub(/(.*[[:space:]]+)?([0-9]+)[[:space:]]blocks.*/, "\\2", "1", $0)
+ }
+ if ( $0 ~ /super[[:space:]][0-9\.]+/ ) {
+ superBlock = gensub(/.*[[:space:]]super[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
+ }
+ if ( $0 ~ /algorithm[[:space:]][0-9\.]+/ ) {
+ algorithm = gensub(/.*[[:space:]]algorithm[[:space:]]([0-9\.]+)[[:space:]].*/, "\\1", "1", $0)
+ }
+ if ( $0 ~ /\[[0-9]+\/[0-9]+\]/ ) {
+ deviceReport = gensub(/.*[[:space:]]\[([0-9]+\/[0-9]+)\][[:space:]].*/, "\\1", "1", $0)
+ uData = gensub(/.*[[:space:]]\[([U_]+)\]/, "\\1", "1", $0)
+ }
+ # need to avoid this: bitmap: 0/10 pages [0KB], 16384KB chunk
+ # while currently all the normal chunks are marked with k, not kb, this can change in the future
+ if ( $0 ~ /[0-9]+[k] chunk/ && $0 !~ /bitmap/ ) {
+ chunkSize = gensub(/(.*) ([0-9]+[k]) chunk.*/, "\\2", "1", $0)
+ }
+ if ( $0 ~ /^resync=/ ) {
+ sub(/resync=/,"")
+ print "resyncStatus," $0
+ }
+ if ( $0 ~ /\[[=]*>[\.]*\].*(resync|recovery)/ ) {
+ recoveryProgressBar = gensub(/.*(\[[=]*>[\.]*\]).*/, "\\1",1,$0)
+ }
+ if ( $0 ~ / (resync|recovery)[[:space:]]*=/ ) {
+ recoveryPercent = gensub(/.* (resync|recovery)[[:space:]]*=[[:space:]]*([0-9\.]+%).*/, "\\1~\\2", 1 )
+ if ( $0 ~ /[[:space:]]\([0-9]+\/[0-9]+\)/ ) {
+ sectorsRecovered = gensub(/.* \(([0-9]+\/[0-9]+)\).*/, "\\1", 1, $0 )
+ }
+ if ( $0 ~ /finish[[:space:]]*=/ ) {
+ finishTime = gensub(/.* finish[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+) .*/, "\\1 \\2", 1, $0 )
+ }
+ if ( $0 ~ /speed[[:space:]]*=/ ) {
+ recoverSpeed = gensub(/.* speed[[:space:]]*=[[:space:]]*([[0-9\.]+)([a-z]+\/[a-z]+)/, "\\1 \\2", 1, $0 )
+ }
+ }
+ if ( $0 ~ /bitmap/ ) {
+ bitmapValues = gensub(/(.*[[:space:]])?bitmap:(.*)/, "\\2", 1, $0 )
+ }
+
+ getline
+ }
+ raidString = device "," deviceState "," raidLevel "," components "," deviceReport "," uData
+ raidString = raidString "," blocks "," superBlock "," algorithm "," chunkSize "," bitmapValues
+ raidString = raidString "," recoveryProgressBar "," recoveryPercent "," sectorsRecovered "," finishTime "," recoverSpeed
+
+ print raidString
+ }
+ ' <<< "$mdstat" ) )
+ IFS="$ORIGINAL_IFS"
+ else
+ if [[ $BSD_TYPE == 'bsd' ]];then
+ get_raid_data_bsd
+ fi
+ fi
+ B_RAID_SET='true'
+ temp_array=${A_RAID_DATA[@]}
+ log_function_data "A_RAID_DATA: $temp_array"
+# echo -e "A_RAID_DATA:\n${temp_array}"
+
+ eval $LOGFE
+}
+
+get_raid_data_bsd()
+{
+ eval $LOGFS
+ local zpool_path=$( type -p zpool 2>/dev/null )
+ local zpool_data=''
+
+ if [[ -n $zpool_path ]];then
+ B_BSD_RAID='true'
+ # bsd sed does not support inserting a true \n so use this trick
+ zpool_data="$( $zpool_path list -v | sed $SED_RX 's/^([^[:space:]])/\
+\1/' )"
+# echo "$zpool_data"
+ IFS=$'\n'
+ A_RAID_DATA=( $(
+ gawk '
+ BEGIN {
+ raidString=""
+ separator=""
+ components=""
+ reportSize=""
+ blocksAvailable=""
+ chunkRaidAllocated=""
+ }
+ /SIZE.*ALLOC/ {
+ sub(/.*ALLOC.*/,"", $0)
+ }
+ /^[^[:space:]]/ {
+ components=""
+ separator=""
+ raidLevel=""
+ device=$1
+ deviceState=$7
+ reportSize=$2
+ blocksAvailable=$4
+ chunkRaidAllocated=$3
+
+ # go to the next line now, this will probably need fixing later with weird data sets
+ getline
+ if ( $1 != "" ) {
+ raidLevel="zfs " $1
+ }
+
+ while ( getline && $1 !~ /^$/ ) {
+ # print $1
+ components = components separator $1
+ separator=" "
+ }
+
+ # print $1
+ raidString = device "," deviceState "," raidLevel "," components "," reportSize "," uData
+ raidString = raidString "," blocksAvailable "," superBlock "," algorithm "," chunkRaidAllocated
+ # none of these are used currently
+ raidString = raidString "," bitmapValues "," recoveryProgressBar "," recoveryPercent
+ raidString = raidString "," sectorsRecovered "," finishTime "," recoverSpeed
+ gsub(/~/,"",raidString)
+ print raidString
+ }' <<< "$zpool_data" ) )
+ IFS="$ORIGINAL_IFS"
+ get_raid_component_data_bsd
+ fi
+ eval $LOGFE
+}
+
+# note, we've already tested for zpool so no further tests required
+get_raid_component_data_bsd()
+{
+ eval $LOGFS
+ local a_raid_data='' array_string='' component='' component_string=''
+ local zpool_status='' device='' separator='' component_status=''
+
+ for (( i=0; i<${#A_RAID_DATA[@]}; i++))
+ do
+ IFS=","
+ a_raid_data=( ${A_RAID_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+ separator=''
+ component_string=''
+ component_status=''
+ zpool_status=''
+ device=${a_raid_data[0]}
+ zpool_status="$( zpool status $device )"
+ # we will remove ONLINE for status and only use OFFLINE/DEGRADED as tests
+ # for print output display of issues with components
+ for component in ${a_raid_data[3]}
+ do
+ component_status=$( gawk '
+ BEGIN {
+ IGNORECASE=1
+ }
+ $1 ~ /^'$component'$/ {
+ sub( /ONLINE/, "", $2 )
+ print "'$component'" $2
+ exit
+ }' <<< "$zpool_status" )
+ component_string="$component_string$separator$component_status"
+ separator=' '
+ done
+ array_string="$device,${a_raid_data[1]},${a_raid_data[2]},$component_string,${a_raid_data[4]}"
+ array_string="$array_string,${a_raid_data[5]},${a_raid_data[6]},${a_raid_data[7]},${a_raid_data[8]}"
+ array_string="$array_string,${a_raid_data[9]},${a_raid_data[10]},${a_raid_data[11]},${a_raid_data[12]},"
+ array_string="$array_string${a_raid_data[13]},${a_raid_data[14]},${a_raid_data[15]}"
+ IFS=","
+ A_RAID_DATA[i]=$array_string
+ IFS="$ORIGINAL_IFS"
+ done
+
+ eval $LOGFE
+}
+# get_raid_data_bsd;exit
+
+# Repos will be added as we get distro package manager data to create the repo data.
+# This method will output the file name also, which is useful to create output that's
+# neat and readable. Each line of the total number contains the following sections,
+# separated by a : for splitting in the print function
+# part one, repo type/string : part two, file name, if present, of info : part 3, repo data
+get_repo_data()
+{
+ eval $LOGFS
+ local repo_file='' repo_data_working='' repo_data_working2='' repo_line='' repo_files=''
+ local repo_name=''
+ local apt_file='/etc/apt/sources.list' yum_repo_dir='/etc/yum.repos.d/' yum_conf='/etc/yum.conf'
+ local pacman_conf='/etc/pacman.conf' pacman_repo_dir='/etc/pacman.d/' pisi_dir='/etc/pisi/'
+ local zypp_repo_dir='/etc/zypp/repos.d/' freebsd_conf='/etc/portsnap.conf'
+
+ # apt - debian, buntus, also sometimes some yum/rpm repos may create apt repos here as well
+ if [[ -f $apt_file || -d $apt_file.d ]];then
+ REPO_DATA="$( grep -Esv '(^[[:space:]]*$|^[[:space:]]*#)' $apt_file $apt_file.d/*.list | sed $SED_RX 's/^(.*)/apt sources:\1/' )"
+ fi
+ # yum - fedora, redhat, centos, etc. Note that rpmforge also may create apt sources
+ # in /etc/apt/sources.list.d/. Therefore rather than trying to assume what package manager is
+ # actually running, inxi will merely note the existence of each repo type for apt/yum.
+ # Also, in rpm, you can install apt-rpm for the apt-get command, so it's not good to check for
+ # only the commands in terms of selecting which repos to show.
+ if [[ -d $yum_repo_dir || -f $yum_conf || -d $zypp_repo_dir ]];then
+ if [[ -d $yum_repo_dir || -f $yum_conf ]];then
+ # older redhats put their yum data in /etc/yum.conf
+ repo_files=$( ls $yum_repo_dir*.repo $yum_conf 2>/dev/null )
+ repo_name='yum'
+ elif [[ -d $zypp_repo_dir ]];then
+ repo_files=$( ls $zypp_repo_dir*.repo 2>/dev/null )
+ repo_name='zypp'
+ fi
+ if [[ -n $repo_files ]];then
+ for repo_file in $repo_files
+ do
+ repo_data_working="$( gawk -v repoFile=$repo_file '
+ # construct the string for the print function to work with, file name: data
+ function print_line( fileName, repoId, repoUrl ){
+ print "'$repo_name' sources:" fileName ":" repoId repoUrl
+ }
+ BEGIN {
+ FS="\n"
+ IGNORECASE=1
+ enabledStatus=""
+ repoTitle=""
+ urlData=""
+ }
+ # this is a hack, assuming that each item has these fields listed, we collect the 3
+ # items one by one, then when the url/enabled fields are set, we print it out and
+ # reset the data. Not elegant but it works. Note that if enabled was not present
+ # we assume it is enabled then, and print the line, reset the variables. This will
+ # miss the last item, so it is printed if found in END
+ /^\[.+\]/ {
+ if ( urlData != "" && repoTitle != "" ){
+ print_line( repoFile, repoTitle, urlData )
+ enabledStatus=""
+ urlData=""
+ repoTitle=""
+ }
+ gsub( /\[|\]/, "", $1 ) # strip out the brackets
+ repoTitle = $1 " ~ "
+ }
+ /^(mirrorlist|baseurl)/ {
+ sub( /(mirrorlist|baseurl)[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
+ urlData = $1
+ }
+ # note: enabled = 1. enabled = 0 means disabled
+ /^enabled[[:space:]]*=/ {
+ enabledStatus = $1
+ }
+ # print out the line if all 3 values are found, otherwise if a new
+ # repoTitle is hit above, it will print out the line there instead
+ {
+ if ( urlData != "" && enabledStatus != "" && repoTitle != "" ){
+ if ( enabledStatus !~ /enabled[[:space:]]*=[[:space:]]*0/ ){
+ print_line( repoFile, repoTitle, urlData )
+ }
+ enabledStatus=""
+ urlData=""
+ repoTitle=""
+ }
+ }
+ END {
+ # print the last one if there is data for it
+ if ( urlData != "" && repoTitle != "" ){
+ print_line( repoFile, repoTitle, urlData )
+ }
+ }
+ ' $repo_file )"
+
+ # then load the global for each file as it gets filled
+ if [[ -n $repo_data_working ]];then
+ if [[ -z $REPO_DATA ]];then
+ REPO_DATA="$repo_data_working"
+ else
+ REPO_DATA="$REPO_DATA
+$repo_data_working"
+ fi
+ repo_data_working=''
+ fi
+ done
+ fi
+ # pacman - archlinux, going to assume that pisi and arch/pacman, etc don't have the above issue with apt/yum
+ elif [[ -f $pacman_conf ]];then
+ # get list of mirror include files, trim white space off ends
+ repo_data_working="$( gawk '
+ BEGIN {
+ FS="="
+ IGNORECASE=1
+ }
+ /^[[:space:]]*Include/ {
+ sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
+ print $2
+ }
+ ' $pacman_conf )"
+ # sort into unique paths only, to be used to search for server = data
+ repo_data_working=$( sort -bu <<< "$repo_data_working" | uniq )
+ repo_data_working="$repo_data_working $pacman_conf"
+ for repo_file in $repo_data_working
+ do
+ if [[ -f $repo_file ]];then
+ # inserting a new line after each found / processed match
+ repo_data_working2="$repo_data_working2$( gawk -v repoFile=$repo_file '
+ BEGIN {
+ FS="="
+ IGNORECASE=1
+ }
+ /^[[:space:]]*Server/ {
+ sub(/^[[:space:]]+|[[:space:]]+$/,"",$2)
+ print "pacman repo servers:" repoFile ":" $2 "\\n"
+ }
+ ' $repo_file )"
+ else
+ echo "Error: file listed in $pacman_conf does not exist - $repo_file"
+ fi
+ done
+ # execute line breaks
+ REPO_DATA="$( echo -e $repo_data_working2 )"
+ # pisi - pardus
+ elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
+ REPO_DATA="$( pisi list-repo )"
+ # now we need to create the structure: repo info: repo path
+ # we do that by looping through the lines of the output and then
+ # putting it back into the <data>:<url> format print repos expects to see
+ # note this structure in the data, so store first line and make start of line
+ # then when it's an http line, add it, and create the full line collection.
+# Pardus-2009.1 [Aktiv]
+# http://packages.pardus.org.tr/pardus-2009.1/pisi-index.xml.bz2
+# Contrib [Aktiv]
+# http://packages.pardus.org.tr/contrib-2009/pisi-index.xml.bz2
+ while read repo_line
+ do
+ repo_line=$( gawk '
+ {
+ # need to dump leading/trailing spaces and clear out color codes for irc output
+ sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
+# gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
+ gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
+ print $0
+ }' <<< $repo_line )
+ if [[ -n $( grep '://' <<< $repo_line ) ]];then
+ repo_data_working="$repo_data_working:$repo_line\n"
+ else
+ repo_data_working="${repo_data_working}pisi repo:$repo_line"
+ fi
+ done <<< "$REPO_DATA"
+ # echo and execute the line breaks inserted
+ REPO_DATA="$( echo -e $repo_data_working )"
+ # Mandriva/Mageia using: urpmq
+ elif [[ -n $( type -p urpmq ) ]];then
+ REPO_DATA="$( urpmq --list-media active --list-url )"
+ # now we need to create the structure: repo info: repo path
+ # we do that by looping through the lines of the output and then
+ # putting it back into the <data>:<url> format print repos expects to see
+ # note this structure in the data, so store first line and make start of line
+ # then when it's an http line, add it, and create the full line collection.
+# Contrib ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/release
+# Contrib Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/contrib/updates
+# Non-free ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/release
+# Non-free Updates ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2011/x86_64/media/non-free/updates
+# Nonfree Updates (Local19) /mnt/data/mirrors/mageia/distrib/cauldron/x86_64/media/nonfree/updates
+ while read repo_line
+ do
+ repo_line=$( gawk '
+ {
+ # need to dump leading/trailing spaces and clear out color codes for irc output
+ sub(/^[[:space:]]+|[[:space:]]+$/,"",$0)
+# gsub(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/,"",$0) # leaving this pattern in case need it
+ gsub(/\e\[([0-9];)?[0-9]+m/,"",$0)
+ print $0
+ }' <<< $repo_line )
+ # urpmq output is the same each line, repo name space repo url, can be:
+ # rsync://, ftp://, file://, http:// OR repo is locally mounted on FS in some cases
+ if [[ -n $( grep -E '(://|[[:space:]]/)' <<< $repo_line ) ]];then
+ # cut out the repo first
+ repo_data_working2=$( grep -Eo '([^[:space:]]+://|[[:space:]]/).*' <<< $repo_line )
+ # then get the repo name string by slicing out the url string
+ repo_name=$( sed "s|[[:space:]]*$repo_data_working2||" <<< $repo_line )
+ repo_data_working="${repo_data_working}urpmq repo:$repo_name:$repo_data_working2\n"
+ fi
+ done <<< "$REPO_DATA"
+ # echo and execute the line breaks inserted
+ REPO_DATA="$( echo -e $repo_data_working )"
+ elif [[ -f $freebsd_conf ]];then
+ REPO_DATA="$( gawk -F '=' -v repoFile=$freebsd_conf '
+ BEGIN {
+ IGNORECASE=1
+ }
+ /^SERVERNAME/ {
+ print "BSD ports servers:" repoFile ":" $2
+ }
+ ' $freebsd_conf )"
+ fi
+ eval $LOGFE
+}
+
+get_runlevel_data()
+{
+ eval $LOGFS
+ local runlvl=''
+ local runlevel_path=$( type -p runlevel )
+ if [[ -n $runlevel_path ]];then
+ runlvl="$( $runlevel_path | gawk '{ print $2 }' )"
+ fi
+ echo $runlvl
+ eval $LOGFE
+}
+
+# note: it appears that at least as of 2014-01-13, /etc/inittab is going to be used for
+# default runlevel in upstart/sysvinit. systemd default is not always set so check to see
+# if it's linked.
+get_runlevel_default()
+{
+ eval $LOGFS
+ local default_runlvl=''
+ local inittab='/etc/inittab'
+ local systemd_default='/etc/systemd/system/default.target'
+ local upstart_default='/etc/init/rc-sysinit.conf'
+
+ # note: systemd systems do not necessarily have this link created
+ if [[ -L $systemd_default ]];then
+ default_runlvl=$( readlink $systemd_default )
+ if [[ -n $default_runlvl ]];then
+ default_runlvl=$( basename $default_runlvl )
+ fi
+ # http://askubuntu.com/questions/86483/how-can-i-see-or-change-default-run-level
+ # note that technically default can be changed at boot but for inxi purposes that does
+ # not matter, we just want to know the system default
+ elif [[ -e $upstart_default ]];then
+ # env DEFAULT_RUNLEVEL=2
+ default_runlvl=$( gawk -F '=' '/^env[[:space:]]+DEFAULT_RUNLEVEL/ {
+ print $2
+ }' $upstart_default )
+ fi
+
+ # handle weird cases where null but inittab exists
+ if [[ -z $default_runlvl && -f $inittab ]];then
+ default_runlvl=$( gawk -F ':' '
+ /^id.*initdefault/ {
+ print $2
+ }' $inittab )
+ fi
+ echo $default_runlvl
+ eval $LOGFE
+}
+
+get_sensors_data()
+{
+ eval $LOGFS
+
+
+ local temp_array=''
+
+ IFS=$'\n'
+ if [[ -n $Sensors_Data ]];then
+ # note: non-configured sensors gives error message, which we need to redirect to stdout
+ # also, -F ':' no space, since some cases have the data starting right after,like - :1287
+ A_SENSORS_DATA=( $(
+ gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" '
+ BEGIN {
+ IGNORECASE=1
+ core0Temp="" # only if all else fails...
+ cpuTemp=""
+ cpuTempReal=""
+ fanWorking=""
+ indexCountaFanMain=0
+ indexCountaFanDefault=0
+ i=""
+ j=""
+ moboTemp=""
+ moboTempReal=""
+ psuTemp=""
+ separator=""
+ sysFanString=""
+ temp1=""
+ temp2=""
+ tempFanType="" # set to 1 or 2
+ tempUnit=""
+ tempWorking=""
+ tempWorkingUnit=""
+ }
+ # new data arriving: gpu temp in sensors, have to skip that
+ /^('"$SENSORS_GPU_SEARCH"')-pci/ {
+ while ( getline && !/^$/ ) {
+ # do nothing, just skip it
+ }
+ }
+ # dumping the extra + signs after testing for them, nobody has negative temps.
+ # also, note gawk treats ° as a space, so we have to get the C/F data
+ # there are some guesses here, but with more sensors samples it will get closer.
+ # note: using arrays starting at 1 for all fan arrays to make it easier overall
+ # more validation because gensub if fails to get match returns full string, so
+ # we have to be sure we are working with the actual real string before assiging
+ # data to real variables and arrays. Extracting C/F degree unit as well to use
+ # when constructing temp items for array.
+ # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign
+ # used, but it is required in testing regex to avoid error.
+ /^(M\/B|MB|SIO|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 )
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+ /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+ /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+ $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( temp1 == "" || tempWorking > 0 ) {
+ temp1=tempWorking
+ }
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+ $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( temp2 == "" || tempWorking > 0 ) {
+ temp2=tempWorking
+ }
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+
+ # final fallback if all else fails, funtoo user showed sensors putting
+ # temp on wrapped second line, not handled
+ /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( core0Temp == "" || tempWorking > 0 ) {
+ core0Temp=tempWorking
+ }
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+
+ # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before
+ # $2 starts (like so :1234 RPM), so skip that space test in regex
+ /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ }
+ /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ }
+ /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ }
+ # note that the counters are dynamically set for fan numbers here
+ # otherwise you could overwrite eg aux fan2 with case fan2 in theory
+ # note: cpu/mobo/ps are 1/2/3
+ # NOTE: test: ! i in array does NOT work, this appears to be an awk/gawk bug
+ /^(AUX(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ for ( i = 4; i < 7; i++ ){
+ if ( i in aFanMain ){
+ ##
+ }
+ else {
+ aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ break
+ }
+ }
+ }
+ /^(AUX([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ for ( i = 5; i < 30; i++ ){
+ if ( i in aFanMain ) {
+ ##
+ }
+ else {
+ sysFanNu = i
+ aFanMain[i]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ break
+ }
+ }
+ }
+ # in rare cases syntax is like: fan1: xxx RPM
+ /^(FAN(1)?[ \t:])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ aFanDefault[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ }
+ /^FAN([2-9]|1[0-9])(.*)[ \t]*([0-9]+)[ \t]RPM/ {
+ fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 )
+ sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 )
+ if ( sysFanNu ~ /^([0-9]+)$/ ) {
+ # add to array if array index does not exist OR if number is > existing number
+ if ( sysFanNu in aFanDefault ) {
+ if ( fanWorking >= aFanDefault[sysFanNu] ) {
+ aFanDefault[sysFanNu]=fanWorking
+ }
+ }
+ else {
+ aFanDefault[sysFanNu]=fanWorking
+ }
+ }
+ }
+
+ END {
+ # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo:
+ # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment
+ if ( temp1 != "" && temp2 != "" ){
+ if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) {
+ tempFanType=userCpuNo
+ }
+ else {
+ # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed
+ # but only if other fan speed is 0
+ if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) {
+ tempFanType=2
+ }
+ else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) {
+ tempFanType=1
+ }
+ # then handle the standard case if these fringe cases are false
+ else if ( temp1 >= temp2 ) {
+ tempFanType=1
+ }
+ else {
+ tempFanType=2
+ }
+ }
+ }
+ # need a case for no temps at all reported, like with old intels
+ else if ( temp2 == "" && cpuTemp == "" ){
+ if ( temp1 == "" && moboTemp == "" ){
+ tempFanType=1
+ }
+ else if ( temp1 != "" && moboTemp == "" ){
+ tempFanType=1
+ }
+ else if ( temp1 != "" && moboTemp != "" ){
+ tempFanType=1
+ }
+ }
+
+ # then get the real cpu temp, best guess is hottest is real
+ if ( cpuTemp != "" ){
+ cpuTempReal=cpuTemp
+ }
+ else if ( tempFanType != "" ){
+ if ( tempFanType == 1 ){
+ cpuTempReal=temp1
+ }
+ else {
+ cpuTempReal=temp2
+ }
+ }
+ else {
+ cpuTempReal=temp1
+ }
+ # if all else fails, use core0 temp if it is present and cpu is null
+ if ( cpuTempReal == "" && core0Temp != "" ) {
+ cpuTempReal=core0Temp
+ }
+
+ # then the real mobo temp
+ if ( moboTemp != "" ){
+ moboTempReal=moboTemp
+ }
+ else if ( tempFanType != "" ){
+ if ( tempFanType == 1 ) {
+ moboTempReal=temp2
+ }
+ else {
+ moboTempReal=temp1
+ }
+ }
+ else {
+ moboTempReal=temp2
+ }
+ # then set the cpu fan speed
+ if ( aFanMain[1] == "" ) {
+ # note, you cannot test for aFanDefault[1] or [2] != ""
+ # because that creates an array item in gawk just by the test itself
+ if ( tempFanType == 1 && 1 in aFanDefault ) {
+ aFanMain[1]=aFanDefault[1]
+ aFanDefault[1]=""
+ }
+ else if ( tempFanType == 2 && 2 in aFanDefault ) {
+ aFanMain[1]=aFanDefault[2]
+ aFanDefault[2]=""
+ }
+ }
+
+ # then we need to get the actual numeric max array count for both fan arrays
+ for (i = 0; i <= 29; i++) {
+ if ( i in aFanMain && i > indexCountaFanMain ) {
+ indexCountaFanMain=i
+ }
+ }
+ for (i = 0; i <= 14; i++) {
+ if ( i in aFanDefault && i > indexCountaFanDefault ) {
+ indexCountaFanDefault=i
+ }
+ }
+
+ # clear out any duplicates. Primary fan real trumps fan working always if same speed
+ for (i = 1; i <= indexCountaFanMain; i++) {
+ if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) {
+ for (j = 1; j <= indexCountaFanDefault; j++) {
+ if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) {
+ aFanDefault[j] = ""
+ }
+ }
+ }
+ }
+
+ # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo
+ # note that gawk is returning true for some test cases when aFanDefault[j] < 5000
+ # which has to be a gawk bug, unless there is something really weird with arrays
+ # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually
+ # assign that value below, the > 5000 test works again, and a print of the value
+ # shows the proper value, so the corruption might be internal in awk.
+ # Note: gensub is the culprit I think, assigning type string for range 501-1000 but
+ # type integer for all others, this triggers true for >
+ for (j = 1; j <= indexCountaFanDefault; j++) {
+ if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) {
+ aFanMain[2] = aFanDefault[j]
+ aFanDefault[j] = ""
+ # then add one if required for output
+ if ( indexCountaFanMain < 2 ) {
+ indexCountaFanMain = 2
+ }
+ }
+ }
+
+ # then construct the sys_fan string for echo, note that iteration 1
+ # makes: fanDefaultString separator null, ie, no space or ,
+ for (j = 1; j <= indexCountaFanDefault; j++) {
+ fanDefaultString = fanDefaultString separator aFanDefault[j]
+ separator=","
+ }
+ separator="" # reset to null for next loop
+ # then construct the sys_fan string for echo
+ for (j = 1; j <= indexCountaFanMain; j++) {
+ fanMainString = fanMainString separator aFanMain[j]
+ separator=","
+ }
+
+ # and then build the temps:
+ if ( moboTempReal != "" ) {
+ moboTempReal = moboTempReal tempUnit
+ }
+ if ( cpuTempReal != "" ) {
+ cpuTempReal = cpuTempReal tempUnit
+ }
+
+ # if they are ALL null, print error message. psFan is not used in output currently
+ if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) {
+ print "No active sensors found. Have you configured your sensors yet?"
+ }
+ else {
+ # then build array arrays:
+ print cpuTempReal "," moboTempReal "," psuTemp
+ # this is for output, a null print line does NOT create a new array index in bash
+ if ( fanMainString == "" ) {
+ fanMainString=","
+ }
+ print fanMainString
+ print fanDefaultString
+ }
+ }' <<< "$Sensors_Data" ) )
+ fi
+
+ IFS="$ORIGINAL_IFS"
+ temp_array=${A_SENSORS_DATA[@]}
+ log_function_data "A_SENSORS_DATA: $temp_array"
+# echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
+ eval $LOGFE
+}
+
+get_sensors_output()
+{
+ local sensors_path=$( type -p sensors ) sensors_data=''
+
+ if [[ -n $sensors_path ]];then
+ sensors_data="$( $sensors_path 2>/dev/null )"
+ if [[ -n "$sensors_data" ]];then
+ # make sure the file ends in newlines then characters, the newlines are lost in the echo unless
+ # the data ends in some characters
+ sensors_data="$sensors_data\n\n###"
+ fi
+ fi
+ echo -e "$sensors_data"
+}
+
+get_shell_data()
+{
+ eval $LOGFS
+
+ local shell_type="$( ps -p $PPID -o comm= 2>/dev/null )"
+ local shell_version=''
+
+ if [[ $B_EXTRA_DATA == 'true' && -n $shell_type ]];then
+ case $shell_type in
+ bash)
+ shell_version=$( get_de_app_version "$shell_type" "^GNU[[:space:]]bash,[[:space:]]version" "4" | \
+ sed $SED_RX 's/(\(.*|-release|-version)//' )
+ ;;
+ # csh/dash use dpkg package version data, debian/buntu only
+ csh)
+ shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
+ ;;
+ dash)
+ shell_version=$( get_de_app_version "$shell_type" "$shell_type" "3" )
+ ;;
+ ksh)
+ shell_version=$( get_de_app_version "$shell_type" "version" "5" )
+ ;;
+ tcsh)
+ shell_version=$( get_de_app_version "$shell_type" "^tcsh" "2" )
+ ;;
+ zsh)
+ shell_version=$( get_de_app_version "$shell_type" "^zsh" "2" )
+ ;;
+ esac
+ fi
+ if [[ -n $shell_version ]];then
+ shell_type="$shell_type $shell_version"
+ fi
+ echo $shell_type
+
+ eval $LOGFS
+}
+
+get_shell_parent()
+{
+ eval $LOGFS
+ local shell_parent='' script_parent=''
+
+ # removed --no-headers to make bsd safe, adding in -j to make output the same
+ script_parent=$( ps -j -fp $PPID 2>/dev/null | gawk '/'"$PPID"'/ { print $3 }' )
+ log_function_data "script parent: $script_parent"
+ shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
+ # no idea why have to do script_parent action twice in su case, but you do, oh well.
+ if [[ $shell_parent == 'su' ]];then
+ script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
+ script_parent=$( ps -j -fp $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $3 }' )
+ shell_parent=$( ps -j -p $script_parent 2>/dev/null | gawk '/'"$script_parent"'/ { print $NF}' )
+ fi
+ echo $shell_parent
+ log_function_data "shell parent final: $shell_parent"
+ eval $LOGFE
+}
+
+# this will be used for some bsd data types
+# args: $1 - option type
+get_sysctl_data()
+{
+ eval $LOGFS
+
+ local sysctl_data=''
+
+ if [[ $B_SYSCTL ]];then
+ sysctl_data="$( sysctl -$1 )"
+ fi
+ # log_function_data "sysctl_data: $sysctl_data"
+ echo "$sysctl_data"
+ eval $LOGFE
+}
+
+get_tty_console_irc()
+{
+ eval $LOGFS
+ local tty_number=''
+ if [[ -n ${IRC_CLIENT} ]];then
+ tty_number=$( gawk '
+ BEGIN {
+ IGNORECASE=1
+ }
+ # if multiple irc clients open, can give wrong results
+ # so make sure to also use the PPID number to get the right tty
+ /.*'$PPID'.*'${IRC_CLIENT}'/ {
+ gsub(/[^0-9]/, "", $7)
+ print $7
+ exit
+ }' <<< "$Ps_aux_Data" )
+ fi
+ log_function_data "tty_number: $tty_number"
+ echo $tty_number
+ eval $LOGFE
+}
+
+get_tty_number()
+{
+ eval $LOGFS
+
+ local tty_number=$( basename "$( tty 2>/dev/null )" | sed 's/[^0-9]*//g' )
+
+ echo $tty_number
+
+ eval $LOGFE
+}
+
+get_unmounted_partition_data()
+{
+ eval $LOGFS
+ local a_unmounted_working='' mounted_partitions='' separator='|' unmounted_fs=''
+ local dev_working='' uuid_working='' label_working='' a_raid_working='' raid_partitions=''
+
+ if [[ $B_PARTITIONS_FILE == 'true' ]];then
+ # set dev disk label/uuid data globals
+ get_partition_dev_data 'label'
+ get_partition_dev_data 'uuid'
+ # load the raid data array here so we can exclude its partitions
+ if [[ $B_RAID_SET != 'true' ]];then
+ get_raid_data
+ fi
+ # sr0 type cd drives are showing up now as unmounted partitions
+ mounted_partitions="scd[0-9]+|sr[0-9]+|cdrom[0-9]*|cdrw[0-9]*|dvd[0-9]*|dvdrw[0-9]*"
+ # create list for slicing out the mounted partitions
+ for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ ))
+ do
+ IFS=","
+ a_unmounted_working=( ${A_PARTITION_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+ if [[ -n ${a_unmounted_working[6]} ]];then
+ mounted_partitions="$mounted_partitions$separator${a_unmounted_working[6]}"
+ fi
+ done
+ # now we need to exclude the mdraid partitions from the unmounted partition output as well
+ for (( i=0; i < ${#A_RAID_DATA[@]}; i++ ))
+ do
+ IFS=","
+ a_raid_working=( ${A_RAID_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+ if [[ -n ${a_raid_working[3]} ]];then
+ raid_partitions=$( sed $SED_RX 's/(\([^\)]*\)|\[[^\]]*\])//g' <<< ${a_raid_working[3]}\
+ | sed 's/[[:space:]]\+/|/g' )
+ mounted_partitions="$mounted_partitions$separator$raid_partitions"
+ fi
+ done
+
+ A_UNMOUNTED_PARTITION_DATA=( $( grep -Ev '[[:space:]]('$mounted_partitions')$' $FILE_PARTITIONS | gawk '
+ BEGIN {
+ IGNORECASE=1
+ }
+ # note that size 1 means it is a logical extended partition container
+ # lvm might have dm-1 type syntax
+ # need to exclude loop type file systems, squashfs for example
+ /[a-z][0-9]+$|dm-[0-9]+$/ && $3 != 1 && $NF !~ /loop/ {
+ size = sprintf( "%.2f", $3*1024/1000**3 )
+ print $4 "," size "G"
+ }' ) )
+
+ for (( i=0; i < ${#A_UNMOUNTED_PARTITION_DATA[@]}; i++ ))
+ do
+ IFS=","
+ a_unmounted_working=( ${A_UNMOUNTED_PARTITION_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+
+ label_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_LABEL" | gawk '{
+ print $(NF - 2)
+ }' )
+ uuid_working=$( grep -E "${a_unmounted_working[0]}$" <<< "$DEV_DISK_UUID" | gawk '{
+ print $(NF - 2)
+ }' )
+ unmounted_fs=$( get_unmounted_partition_filesystem "/dev/${a_unmounted_working[0]}" )
+
+ IFS=","
+ A_UNMOUNTED_PARTITION_DATA[i]=${a_unmounted_working[0]}","${a_unmounted_working[1]}","$label_working","$uuid_working","$unmounted_fs
+ IFS="$ORIGINAL_IFS"
+ done
+ fi
+# echo "${A_PARTITION_DATA[@]}"
+# echo "${A_UNMOUNTED_PARTITION_DATA[@]}"
+ eval $LOGFE
+}
+
+# a few notes, normally file -s requires root, but you can set user rights in /etc/sudoers.
+# list of file systems: http://en.wikipedia.org/wiki/List_of_file_systems
+# args: $1 - /dev/<disk><part> to be tested for
+get_unmounted_partition_filesystem()
+{
+ eval $LOGFS
+ local partition_filesystem='' sudo_command=''
+
+ if [[ $B_FILE_TESTED != 'true' ]];then
+ B_FILE_TESTED='true'
+ FILE_PATH=$( type -p file )
+ fi
+
+ if [[ $B_SUDO_TESTED != 'true' ]];then
+ B_SUDO_TESTED='true'
+ SUDO_PATH=$( type -p sudo )
+ fi
+
+ if [[ -n $FILE_PATH && -n $1 ]];then
+ # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out
+ # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying
+ # important: -n makes it non interactive, no prompt for password
+ if [[ $B_ROOT != 'true' && -n $SUDO_PATH ]];then
+ sudo_command='sudo -n '
+ fi
+ # this will fail if regular user and no sudo present, but that's fine, it will just return null
+ # note the hack that simply slices out the first line if > 1 items found in string
+ # also, if grub/lilo is on partition boot sector, no file system data is available
+ # BSD fix: -Eio -Em 1
+ 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 '.*' )
+ if [[ -n $partition_filesystem ]];then
+ echo $partition_filesystem
+ fi
+ fi
+ eval $LOGFE
+}
+
+## return uptime string
+get_uptime()
+{
+ eval $LOGFS
+ ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
+ local uptime_value="$( uptime | gawk '{
+ a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
+ print a
+ }' )"
+ echo "$uptime_value"
+ log_function_data "uptime_value: $uptime_value"
+ eval $LOGFE
+}
+
+get_weather_data()
+{
+ eval $LOGFS
+
+ local location_site='http://geoip.ubuntu.com/lookup'
+ local weather_feed='http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query='
+ local weather_spider='http://wunderground.com/'
+ local data_grab_error='' wget_error=0
+ local b_test_loc=false b_test_weather=false b_debug=false
+ local test_dir="$HOME/bin/scripts/inxi/data/weather/"
+ local test_location='location2.xml' test_weather='weather-feed.xml'
+ local location_data='' location='' weather_data='' location_array_value='' a_location=''
+ local weather_array_value='' site_elevation='' temp_array=''
+
+ # first we get the location data, once that is parsed and handled, we move to getting the
+ # actual weather data, assuming no errors
+ if [[ -n $ALTERNATE_WEATHER_LOCATION ]];then
+ # note, this api does not support spaces in names, replace spaces with + sign.
+ location=$ALTERNATE_WEATHER_LOCATION
+ # echo $ALTERNATE_WEATHER_LOCATION;exit
+ else
+ if [[ $b_test_loc != 'true' ]];then
+ location_data=$( wget -q -t 1 -T $WGET_TIMEOUT -O- $location_site || wget_error=$? )
+ log_function_data "$location_data"
+ if [[ $wget_error -ne 0 ]];then
+ data_grab_error="Error: location server up but download error - wget: $wget_error"
+ fi
+ wget_error=0
+ else
+ if [[ -f $test_dir$test_location ]];then
+ location_data="$( cat $test_dir$test_location )"
+ else
+ data_grab_error="Error: location xml local file not found."
+ fi
+ fi
+ if [[ -n $data_grab_error ]];then
+ :
+ elif [[ -z $( grep -i '<Response' <<< $location_data ) ]];then
+ data_grab_error="Error: location downloaded but data contains no xml."
+ else
+ # clean up xml and make easy to process with newlines, note, bsd sed has no support for inserting
+ # \n dircctly so we have to use this hack
+ # location_data="$( sed $SED_RX 's|><|>\n<|g' <<< $location_data )"
+ location_data="$( sed $SED_RX 's|><|>\
+<|g' <<< $location_data )"
+ # echo -e "ld:\n$location_data"
+ location_array_value=$( gawk '
+ function clean(data) {
+ returnData=""
+ # some lines might be empty, so ignore those
+ if (data !~ /^<[^>]+>$/ ) {
+ returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
+ }
+ return returnData
+ }
+ BEGIN {
+ IGNORECASE=1
+ locationString=""
+ countryCode=""
+ countryCode3=""
+ countryName=""
+ regionCode=""
+ regionName=""
+ city=""
+ postalCode=""
+ latitude=""
+ longitude=""
+ timeZone=""
+ areaCode=""
+ }
+ /CountryCode/ {
+ if ( $0 ~ /CountryCode3/ ){
+ countryCode3=clean($0)
+ }
+ else {
+ countryCode=clean($0)
+ }
+ }
+ /CountryName/ {
+ countryName = clean($0)
+ }
+ /RegionCode/ {
+ regionCode = clean($0)
+ }
+ /RegionName/ {
+ regionName = clean($0)
+ }
+ /City/ {
+ city = clean($0)
+ }
+ /ZipPostalCode/ {
+ postalCode = clean($0)
+ }
+ /Latitude/ {
+ latitude = clean($0)
+ }
+ /Longitude/ {
+ longitude = clean($0)
+ }
+ /TimeZone/ {
+ timeZone = clean($0)
+ }
+ END {
+ locationString = city ";" regionCode ";" regionName ";" countryName ";" countryCode ";" countryCode3
+ locationString = locationString ";" latitude "," longitude ";" postalCode ";" timeZone
+ print locationString
+ }' <<< "$location_data" )
+ fi
+ A_WEATHER_DATA[0]=$location_array_value
+ IFS=";"
+ a_location=( ${A_WEATHER_DATA[0]} )
+ IFS="$ORIGINAL_IFS"
+
+ # assign location, cascade from most accurate
+ # latitude,longitude first
+ if [[ -n ${a_location[6]} ]];then
+ location="${a_location[6]}"
+ # city,state next
+ elif [[ -n ${a_location[0]} && -n ${a_location[1]} ]];then
+ location="${a_location[0]},${a_location[1]}"
+ # postal code last, that can be a very large region
+ elif [[ -n ${a_location[7]} ]];then
+ location=${a_location[7]}
+ fi
+ fi
+ if [[ $b_debug == 'true' ]];then
+ echo -e "location array:\n${A_WEATHER_DATA[0]}"
+ echo "location: $location"
+ fi
+ log_function_data "location: $location"
+
+ if [[ -z $location && -z $data_grab_error ]];then
+ data_grab_error="Error: location data downloaded but no location detected."
+ fi
+
+ # now either dump process or go on to get weather data
+ if [[ -z $data_grab_error ]];then
+ if [[ $b_test_weather != 'true' ]];then
+ weather_data="$( wget -q -t 1 -T $WGET_TIMEOUT -O- $weather_feed"$location" || wget_error=$? )"
+ if [[ $wget_error -ne 0 ]];then
+ data_grab_error="Error: weather server up but download error - wget: $wget_error"
+ fi
+ log_function_data "$weather_data"
+ else
+ if [[ -f $test_dir$test_weather ]];then
+ weather_data="$( cat $test_dir$test_weather)"
+ else
+ data_grab_error="Error: weather feed xml local file not found."
+ fi
+ fi
+ if [[ -z $data_grab_error && -z $( grep -i '<current_observation' <<< $weather_data ) ]];then
+ data_grab_error="Error: weather data downloaded but shows no xml start."
+ fi
+ if [[ -z $data_grab_error ]];then
+ # trim off zeros
+ weather_data=$( sed 's/^[[:space:]]*//' <<< "$weather_data" )
+ site_elevation=$( grep -im 1 '<elevation>' <<< "$weather_data" | sed $SED_RX -e 's/<[^>]*>//g' \
+ -e 's/\.[0-9]*//' )
+ # we need to grab the location data from the feed for remote checks
+ if [[ -n $ALTERNATE_WEATHER_LOCATION && -n $weather_data ]];then
+ location_data=$( sed -e '/<current_observation>/,/<display_location>/d' -e '/<\/display_location>/,/<\/current_observation>/d' <<< "$weather_data" )
+ # echo -e "ld1:\n$location_data"
+ A_WEATHER_DATA[0]=$( gawk '
+ function clean(data) {
+ returnData=""
+ # some lines might be empty, so ignore those
+ if (data !~ /^<[^>]+>$/ ) {
+ returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
+ gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
+ }
+ return returnData
+ }
+ BEGIN {
+ IGNORECASE=1
+ city=""
+ state=""
+ country=""
+ }
+ /<city>/ {
+ city=clean($0)
+ }
+ /<state>/ {
+ state=clean($0)
+ }
+ /<country>/ {
+ country=clean($0)
+ }
+ END {
+ print city ";" state ";;;;" country
+ }' <<< "$location_data" )
+ # echo -e "location:\n${A_WEATHER_DATA[0]}"
+ fi
+
+ # clean off everything before/after observation_location
+ weather_data=$( sed -e '/<current_observation>/,/<observation_location>/d' \
+ -e '/<icons>/,/<\/current_observation>/d' <<< "$weather_data" -e 's/^[[:space:]]*$//g' -e '/^$/d' )
+
+ # echo "$weather_data";exit
+ weather_array_value=$( gawk -v siteElevation="$site_elevation" '
+ function clean(data) {
+ returnData=""
+ # some lines might be empty, so ignore those
+ if (data !~ /^<[^>]+>$/ ) {
+ returnData=gensub(/(.*>)([^<]*)(<.*)/, "\\2", 1, data)
+ gsub(/^[[:space:]]+|[[:space:]]+$|^NA$|^N\/A$/, "", returnData)
+ }
+ return returnData
+ }
+ BEGIN {
+ IGNORECASE=1
+ observationTime=""
+ localTime=""
+ weather=""
+ tempString=""
+ humidity=""
+ windString=""
+ pressureString=""
+ dewpointString=""
+ heatIndexString=""
+ windChillString=""
+ weatherString=""
+ }
+ /observation_time>/ {
+ observationTime=clean($0)
+ sub(/Last Updated on /, "", observationTime )
+ }
+ /local_time>/ {
+ localTime=clean($0)
+ }
+ /<weather/ {
+ weather=clean($0)
+ }
+ /temperature_string/ {
+ tempString=clean($0)
+ }
+ /relative_humidity/ {
+ humidity=clean($0)
+ }
+ /wind_string/ {
+ windString=clean($0)
+ }
+ /pressure_string/ {
+ pressureString=clean($0)
+ }
+ /heat_index_string/ {
+ heatIndexString=clean($0)
+ }
+ /windchill_string/ {
+ windChillString=clean($0)
+ }
+ END {
+ weatherString = observationTime ";" localTime ";" weather ";" tempString ";" humidity
+ weatherString = weatherString ";" windString ";" pressureString ";" dewpointString ";" heatIndexString
+ weatherString = weatherString ";" windChillString ";" siteElevation
+ print weatherString
+ }' <<< "$weather_data" )
+ fi
+ if [[ -z $weather_array_value ]];then
+ data_grab_error="Error: weather info downloaded but no data detected."
+ else
+ A_WEATHER_DATA[1]=$weather_array_value
+ fi
+ fi
+ # now either dump process or go on to get weather data
+ if [[ -n $data_grab_error ]];then
+ A_WEATHER_DATA=$data_grab_error
+ log_function_data "data grab error: $data_grab_error"
+ fi
+
+ if [[ $b_debug == 'true' ]];then
+ echo "site_elevation: $site_elevation"
+ echo "${A_WEATHER_DATA[1]}"
+ fi
+ temp_array=${A_WEATHER_DATA[@]}
+ log_function_data "A_WEATHER_DATA: $temp_array"
+
+ eval $LOGFE
+}
+# ALTERNATE_WEATHER_LOCATION='portland,or'
+# get_weather_data;exit
+
+#### -------------------------------------------------------------------
+#### special data handling for specific options and conditions
+#### -------------------------------------------------------------------
+
+# args: $1 - string to strip color code characters out of
+# returns count of string length minus colors
+calculate_line_length()
+{
+ local string="$1"
+ # ansi: \e[1;34m irc: \x0312
+ 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 )
+ count=${#string}
+ echo $count
+}
+
+## multiply the core count by the data to be calculated, bmips, cache
+# args: $1 - string to handle; $2 - cpu count
+calculate_multicore_data()
+{
+ eval $LOGFS
+ local string_number=$1 string_data=''
+
+ if [[ -n $( grep -Ei '( mb| kb)' <<< $1 ) ]];then
+ string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output
+ string_number=$( gawk '{print $1}' <<< $1 )
+ fi
+ # handle weird error cases where it's not a number
+ if [[ -n $( grep -E '^[0-9\.,]+$' <<< $string_number ) ]];then
+ string_number=$( echo $string_number $2 | gawk '{
+ total = $1*$2
+ print total
+ }' )
+ elif [[ $string_number == '' ]];then
+ string_number='N/A'
+ else
+ # I believe that the above returns 'unknown' by default so no need for extra text
+ string_number="$string_number "
+ fi
+ echo "$string_number$string_data"
+ log_function_data "string_numberstring_data: $string_number$string_data"
+ eval $LOGFE
+}
+
+# prints out shortened list of flags, the main ones of interest
+# args: $1 - string of cpu flags to process
+process_cpu_flags()
+{
+ eval $LOGFS
+
+ local cpu_flags_working=$1
+ local bits=$( uname -m | grep 64 )
+
+ # no need to show pae for 64 bit cpus, it's pointless
+ if [[ -n $bits ]];then
+ cpu_flags_working=$( sed 's/[[:space:]]*pae//' <<< "$cpu_flags_working" )
+ fi
+ # must have a space after last item in list for RS=" "
+ cpu_flags_working="$cpu_flags_working "
+
+ # nx = AMD stack protection extensions
+ # lm = Intel 64bit extensions
+ # sse, sse2, pni = sse1,2,3,4,5 gfx extensions
+ # svm = AMD pacifica virtualization extensions
+ # vmx = Intel IVT (vanderpool) virtualization extensions
+ cpu_flags=$(
+ echo "$cpu_flags_working" | gawk '
+ BEGIN {
+ RS=" "
+ count = 0
+ i = 1 # start at one because of for increment issue
+ flag_string = ""
+ }
+
+ /^(lm|nx|pae|pni|svm|vmx|(sss|ss)e([2-9])?([a-z])?(_[0-9])?)$/ {
+ if ( $0 == "pni" ){
+ a_flags[i] = "sse3"
+ }
+ else {
+ a_flags[i] = $0
+ }
+ i++
+ }
+ END {
+ count = asort( a_flags )
+ # note: why does gawk increment before the loop and not after? weird.
+ for ( i=0; i <= count; i++ ){
+ if ( flag_string == "" ) {
+ flag_string = a_flags[i]
+ }
+ else {
+ flag_string = flag_string " " a_flags[i]
+ }
+ }
+ print flag_string
+ }' )
+
+ #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' '))
+ if [[ -z $cpu_flags ]];then
+ cpu_flags="-"
+ fi
+ echo "$cpu_flags"
+ log_function_data "cpu_flags: $cpu_flags"
+ eval $LOGFE
+}
+
+#### -------------------------------------------------------------------