+ local zpool_path=$( type -p zpool 2>/dev/null )
+ local zpool_data='' zpool_arg='v'
+
+ if [[ -n $zpool_path ]];then
+ B_BSD_RAID='true'
+ # bsd sed does not support inserting a true \n so use this trick
+ # some zfs does not have -v
+ if $zpool_path list -v &>/dev/null;then
+ zpool_data="$( $zpool_path list -v 2>/dev/null | sed $SED_RX 's/^([^[:space:]])/\
+\1/' )"
+ else
+ zpool_data="$( $zpool_path list 2>/dev/null | sed $SED_RX 's/^([^[:space:]])/\
+\1/' )"
+ zpool_arg='no-v'
+ fi
+# echo "$zpool_data"
+ IFS=$'\n'
+ A_RAID_DATA=( $(
+ gawk '
+ BEGIN {
+ IGNORECASE=1
+ raidString=""
+ separator=""
+ components=""
+ reportSize=""
+ blocksAvailable=""
+ chunkRaidAllocated=""
+ }
+ /SIZE.*ALLOC/ {
+ sub(/.*ALLOC.*/,"", $0)
+ }
+ # gptid/d874c7e7-3f6d-11e4-b7dc-080027ea466c
+ /^[^[:space:]]/ {
+ components=""
+ separator=""
+ raidLevel=""
+ device=$1
+ deviceState=$7
+ reportSize=$2
+ blocksAvailable=$4
+ chunkRaidAllocated=$3
+
+ getline
+ # raid level is the second item in the output, unless it is not, sometimes it is absent
+ if ( $1 != "" ) {
+ if ( $1 ~ /raid|mirror/ ) {
+ raidLevel="zfs " $1
+ }
+ else {
+ raidLevel="zfs-no-raid"
+ components = $1
+ separator=" "
+ }
+ }
+
+ while ( getline && $1 !~ /^$/ ) {
+ # https://blogs.oracle.com/eschrock/entry/zfs_hot_spares
+ if ($1 ~ /spares/) {
+ getline
+ }
+ # print $1
+ components = components separator $1
+ separator=" "
+ }
+ # some issues if we use ~ here
+ gsub(/\//,"%",components)
+ # 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"
+ # pass the zpool type, so we know how to get the components
+ get_raid_component_data_bsd "$zpool_arg"
+ fi
+ eval $LOGFE
+}
+
+# note, we've already tested for zpool so no further tests required
+# args: $1 - zpool type, v will have a single row output, no-v has stacked for components
+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
+ # note: different zfs outputs vary, some have the components listed by line
+ if [[ $1 == 'v' ]];then
+ for component in ${a_raid_data[3]}
+ do
+ component_status=$( gawk '
+ BEGIN {
+ IGNORECASE=1
+ separator=""
+ }
+ {
+ gsub(/\//,"%",$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]}"
+ else
+ component_string=$( gawk '
+ BEGIN {
+ IGNORECASE=1
+ separator=""
+ components=""
+ raidLevel=""
+ }
+ $1 ~ /^'$device'$/ {
+ while ( getline && !/^$/ ) {
+ # raid level is the second item in the output, unless it is not, sometimes it is absent
+ if ( $1 != "" ) {
+ if ( raidLevel == "" ) {
+ if ( $1 ~ /raid|mirror/ ) {
+ raidLevel="zfs " $1
+ getline
+ }
+ else {
+ raidLevel="zfs-no-raid"
+ }
+ }
+ }
+ # https://blogs.oracle.com/eschrock/entry/zfs_hot_spares
+ if ($1 ~ /spares/) {
+ getline
+ }
+ sub( /ONLINE/, "", $2 )
+ components=components separator $1 separator $2
+ separator=" "
+ }
+ print raidLevel "," components
+ }' <<< "$zpool_status" )
+ # note: component_string is raid type AND components
+ array_string="$device,${a_raid_data[1]},$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]}"
+ fi
+ IFS=","
+ A_RAID_DATA[i]=$array_string
+ IFS="$ORIGINAL_IFS"
+ done
+
+ eval $LOGFE
+}
+# get_raid_data_bsd;exit
+
+get_ram_data()
+{
+ eval $LOGFS
+
+ local a_temp='' array_string=''
+
+ get_dmidecode_data
+
+ if [[ -n $DMIDECODE_DATA ]];then
+ if [[ $DMIDECODE_DATA == 'dmidecode-error-'* ]];then
+ A_MEMORY_DATA[0]=$DMIDECODE_DATA
+ # please note: only dmidecode version 2.11 or newer supports consistently the -s flag
+ else
+ IFS=$'\n'
+ A_MEMORY_DATA=( $(
+ gawk -F ':' '
+ BEGIN {
+ IGNORECASE=1
+ arrayHandle=""
+ bankLocator=""
+ clockSpeed=""
+ configuredClockSpeed=""
+ dataWidth=""
+ deviceManufacturer=""
+ devicePartNumber=""
+ deviceSerialNumber=""
+ deviceSpeed=""
+ deviceType=""
+ deviceTypeDetail=""
+ deviceSize=""
+ errorCorrection=""
+ formFactor=""
+ handle=""
+ location=""
+ locator=""
+ aArrayData[0,"maxCapacity5"]=0
+ aArrayData[0,"maxCapacity16"]=0
+ aArrayData[0,"usedCapacity"]=0
+ aArrayData[0,"maxModuleSize"]=0
+ aArrayData[0,"derivedModuleSize"]=0
+ aArrayData[0,"deviceCount5"]=0
+ aArrayData[0,"deviceCount16"]=0
+ aArrayData[0,"deviceCountFound"]=0
+ aArrayData[0,"moduleVoltage5"]=""
+ moduleVoltage=""
+ numberOfDevices=""
+ primaryType=""
+ totalWidth=""
+ use=""
+ i=0
+ j=0
+ k=0
+ bDebugger1="false"
+ dDebugger2="false"
+ bType5="false"
+ }
+ function calculateSize(data,size) {
+ if ( data ~ /^[0-9]+[[:space:]]*[GMTP]B/) {
+ if ( data ~ /GB/ ) {
+ data=gensub(/([0-9]+)[[:space:]]*GB/,"\\1",1,data) * 1024
+ }
+ else if ( data ~ /MB/ ) {
+ data=gensub(/([0-9]+)[[:space:]]*MB/,"\\1",1,data)
+ }
+ else if ( data ~ /TB/ ) {
+ data=gensub(/([0-9]+)[[:space:]]*TB/,"\\1",1,data) * 1024 * 1000
+ }
+ else if ( data ~ /PB/ ) {
+ data=gensub(/([0-9]+)[[:space:]]*TB/,"\\1",1,data) * 1024 * 1000 * 1000
+ }
+ if (data ~ /^[0-9][0-9]+$/ && data > size ) {
+ size=data
+ }
+ }
+ return size
+ }
+ /^Table[[:space:]]+at[[:space:]]/ {
+ bType5="false"
+ # we need to start count here because for testing > 1 array, and we want always to have
+ # the actual module data assigned to the right primary array, even when it is out of
+ # position in dmidecode output
+ i=0
+ j=0
+ k++
+ }
+ # {print k ":k:" $0}
+ /^Handle .* DMI[[:space:]]+type[[:space:]]+5(,|[[:space:]])/ {
+ while ( getline && !/^$/ ) {
+ if ( $1 == "Maximum Memory Module Size" ) {
+ aArrayData[k,"maxModuleSize"]=calculateSize($2,aArrayData[k,"maxModuleSize"])
+ # print "mms:" aArrayData[k,"maxModuleSize"] ":" $2
+ }
+ if ($1 == "Maximum Total Memory Size") {
+ aArrayData[k,"maxCapacity5"]=calculateSize($2,aArrayData[k,"maxCapacity5"])
+ }
+ if ( $1 == "Memory Module Voltage" ) {
+ aArrayData[k,"moduleVoltage5"]=$2
+ }
+ }
+ aArrayData[k,"data-type"]="memory-array"
+ # print k ":data5:"aArrayData[k,"data-type"]
+ bType5="true"
+ }
+ /^Handle .* DMI[[:space:]]+type[[:space:]]+6(,|[[:space:]])/ {
+ while ( getline && !/^$/ ) {
+ if ( $1 == "Installed Size" ) {
+ # get module size
+ aMemory[k,j,18]=calculateSize($2,0)
+ # get data after module size
+ sub(/ Connection/,"",$2)
+ sub(/^[0-9]+[[:space:]]*[MGTP]B[[:space:]]*/,"",$2)
+ aMemory[k,j,16]=$2
+ }
+ if ( $1 == "Current Speed" ) {
+ aMemory[k,j,17]=$2
+ }
+ }
+ j++
+ }
+
+ /^Handle .* DMI[[:space:]]+type[[:space:]]+16/ {
+ arrayHandle=gensub(/Handle[[:space:]]([0-9a-zA-Z]+)([[:space:]]|,).*/,"\\1",$0)
+ while ( getline && !/^$/ ) {
+ # print $0
+ if ( $1 == "Maximum Capacity") {
+ aArrayData[k,"maxCapacity16"]=calculateSize($2,aArrayData[k,"maxCapacity16"])
+ #print "mc:" aArrayData[k,"maxCapacity16"] ":" $2
+ }
+ # note: these 3 have cleaned data in get_dmidecode_data, so replace stuff manually
+ if ( $1 == "Location") {
+ sub(/[[:space:]]Or[[:space:]]Motherboard/,"",$2)
+ location=$2
+ if ( location == "" ){
+ location="System Board"
+ }
+ }
+ if ( $1 == "Use") {
+ use=$2
+ if ( use == "" ){
+ use="System Memory"
+ }
+ }
+ if ( $1 == "Error Correction Type") {
+ errorCorrection=$2
+ if ( errorCorrection == "" ){
+ errorCorrection="None"
+ }
+ }
+ if ( $1 == "Number of Devices") {
+ numberOfDevices=$2
+ }
+ }
+ aArrayData[k,"data-type"]="memory-array"
+ # print k ":data16:"aArrayData[k,"data-type"]
+ aArrayData[k,"handle"]=arrayHandle
+ aArrayData[k,"location"]=location
+ aArrayData[k,"deviceCount16"]=numberOfDevices
+ aArrayData[k,"use"]=use
+ aArrayData[k,"errorCorrection"]=errorCorrection
+
+ # reset
+ primaryType=""
+ arrayHandle=""
+ location=""
+ numberOfDevices=""
+ use=""
+ errorCorrection=""
+ moduleVoltage=""
+
+ aDerivedModuleSize[k+1]=0
+ aArrayData[k+1,"deviceCountFound"]=0
+ aArrayData[k+1,"maxCapacity5"]=0
+ aArrayData[k+1,"maxCapacity16"]=0
+ aArrayData[k+1,"maxModuleSize"]=0
+ }
+ /^Handle .* DMI[[:space:]]+type[[:space:]]+17/ {
+ while ( getline && !/^$/ ) {
+ if ( $1 == "Array Handle") {
+ arrayHandle=$2
+ }
+ if ( $1 == "Data Width") {
+ dataWidth=$2
+ }
+ if ( $1 == "Total Width") {
+ totalWidth=$2
+ }
+ if ( $1 == "Size") {
+ # do not try to guess from installed modules, only use this to correct type 5 data
+ aArrayData[k,"derivedModuleSize"]=calculateSize($2,aArrayData[k,"derivedModuleSize"])
+ workingSize=calculateSize($2,0)
+ if ( workingSize ~ /^[0-9][0-9]+$/ ){
+ aArrayData[k,"deviceCountFound"]++
+ # build up actual capacity found for override tests
+ aArrayData[k,"usedCapacity"]=workingSize + aArrayData[k,"usedCapacity"]
+ }
+ # print aArrayData[k,"derivedModuleSize"] " dm:" k ":mm " aMaxModuleSize[k] " uc:" aArrayData[k,"usedCapacity"]
+ # we want any non real size data to be preserved
+ if ( $2 ~ /^[0-9]+[[:space:]]*[MTPG]B/ ) {
+ deviceSize=workingSize
+ }
+ else {
+ deviceSize=$2
+ }
+ }
+ if ( $1 == "Locator") {
+ # sub(/.*_/,"",$2)
+ #sub(/RAM slot #|^DIMM/, "Slot",$2)
+ sub(/RAM slot #/, "Slot",$2)
+
+ #locator=toupper($2)
+ locator=$2
+ }
+ if ( $1 == "Bank Locator") {
+ #sub(/_.*/,"",$2)
+ #sub(/RAM slot #|Channel|Chan/,"bank",$2)
+ #sub(/RAM slot #|Channel|Chan/,"bank",$2)
+ #bankLocator=toupper($2)
+ bankLocator=$2
+ }
+ if ( $1 == "Form Factor") {
+ formFactor=$2
+ }
+ if ( $1 == "Type") {
+ deviceType=$2
+ }
+ if ( $1 == "Type Detail") {
+ deviceTypeDetail=$2
+ }
+ if ( $1 == "Speed") {
+ deviceSpeed=$2
+ }
+ if ( $1 == "Configured Clock Speed") {
+ configuredClockSpeed=$2
+ }
+ if ( $1 == "Manufacturer") {
+ gsub(/(^[0]+$|Undefined.*|.*Manufacturer.*)/,"",$2)
+ deviceManufacturer=$2
+ }
+ if ( $1 == "Part Number") {
+ sub(/(^[0]+$||.*Module.*|Undefined.*)/,"",$2)
+ devicePartNumber=$2
+ }
+ if ( $1 == "Serial Number") {
+ gsub(/(^[0]+$|Undefined.*)/,"",$2)
+ deviceSerialNumber=$2
+ }
+ }
+ # because of the wide range of bank/slot type data, we will just use
+ # the one that seems most likely to be right. Some have: Bank: SO DIMM 0 slot: J6A
+ # so we dump the useless data and use the one most likely to be visibly correct
+ if ( bankLocator ~ /DIMM/ ) {
+ mainLocator=bankLocator
+ }
+ else {
+ mainLocator=locator
+ }
+ # sometimes the data is just wrong, they reverse total/data. data I believe is
+ # used for the actual memory bus width, total is some synthetic thing, sometimes missing.
+ # note that we do not want a regular string comparison, because 128 bit memory buses are
+ # in our future, and 128 bits < 64 bits with string compare
+ intData=gensub(/(^[0-9]+).*/,"\\1",1,dataWidth)
+ intTotal=gensub(/(^[0-9]+).*/,"\\1",1,totalWidth)
+ if (intData != "" && intTotal != "" && intData > intTotal ) {
+ tempWidth=dataWidth
+ dataWidth=totalWidth
+ totalWidth=tempWidth
+ }
+
+ aMemory[k,i,0]="memory-device"
+ aMemory[k,i,1]=arrayHandle
+ aMemory[k,i,2]=deviceSize
+ aMemory[k,i,3]=bankLocator
+ aMemory[k,i,4]=locator
+ aMemory[k,i,5]=formFactor
+ aMemory[k,i,6]=deviceType
+ aMemory[k,i,7]=deviceTypeDetail
+ aMemory[k,i,8]=deviceSpeed
+ aMemory[k,i,9]=configuredClockSpeed
+ aMemory[k,i,10]=dataWidth
+ aMemory[k,i,11]=totalWidth
+ aMemory[k,i,12]=deviceManufacturer
+ aMemory[k,i,13]=devicePartNumber
+ aMemory[k,i,14]=deviceSerialNumber
+ aMemory[k,i,15]=mainLocator
+
+ primaryType=""
+ arrayHandle=""
+ deviceSize=""
+ bankLocator=""
+ locator=""
+ mainLocator=""
+ mainLocator=""
+ formFactor=""
+ deviceType=""
+ deviceTypeDetail=""
+ deviceSpeed=""
+ configuredClockSpeed=""
+ dataWidth=""
+ totalWidth=""
+ deviceManufacturer=""
+ devicePartNumber=""
+ deviceSerialNumber=""
+ i++
+ }
+ END {
+ ## CRITICAL: gawk keeps changing integers to strings, so be explicit with int() in math
+ # print primaryType "," arrayHandle "," location "," maxCapacity "," numberOfDevices "," use "," errorCorrection "," maxModuleSize "," moduleVoltage
+
+ # print primaryType "," arrayHandle "," deviceSize "," bankLocator "," locator "," formFactor "," deviceType "," deviceTypeDetail "," deviceSpeed "," configuredClockSpeed "," dataWidth "," totalWidth "," deviceManufacturer "," devicePartNumber "," deviceSerialNumber "," mainLocator
+
+ for ( m=1;m<=k;m++ ) {
+ estCap=""
+ estMod=""
+ unit=""
+ altCap=0
+ workingMaxCap=int(aArrayData[m,"maxCapacity16"])
+
+ if ( bDebugger1 == "true" ){
+ print ""
+ print "count: " m
+ print "1: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"]
+ }
+ # 1: if max cap 1 is null, and max cap 2 not null, use 2
+ if ( workingMaxCap == 0 ) {
+ if ( aArrayData[m,"maxCapacity5"] != 0 ) {
+ workingMaxCap=aArrayData[m,"maxCapacity5"]
+ }
+ }
+ if ( aArrayData[m,"deviceCount16"] == "" ) {
+ aArrayData[m,"deviceCount16"] = 0
+ }
+ if ( bDebugger1 == "true" ){
+ print "2: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"]
+ }
+ # 2: now check to see if actually found module sizes are > than listed max module, replace if >
+ if (aArrayData[m,"maxModuleSize"] != 0 && aArrayData[m,"derivedModuleSize"] != 0 && int(aArrayData[m,"derivedModuleSize"]) > int(aArrayData[m,"maxModuleSize"]) ) {
+ aArrayData[m,"maxModuleSize"]=aArrayData[m,"derivedModuleSize"]
+ estMod=" (est)"
+ }
+ aArrayData[m,"maxModuleSize"]=int(aArrayData[m,"maxModuleSize"])
+ aArrayData[m,"derivedModuleSize"]=int(aArrayData[m,"derivedModuleSize"])
+ aArrayData[m,"usedCapacity"]=int(aArrayData[m,"usedCapacity"])
+ workingMaxCap=int(workingMaxCap)
+
+ # note: some cases memory capacity == max module size, so one stick will fill it
+ # but I think only with cases of 2 slots does this happen, so if > 2, use the count of slots.
+ if ( bDebugger1 == "true" ){
+ print "3: fmod: " aArrayData[m,"deviceCountFound"] " :modc: " aArrayData[m,"deviceCount16"] " :maxc1: " aArrayData[m,"maxCapacity5"] " :maxc2: " aArrayData[m,"maxCapacity16"]
+ }
+ if (workingMaxCap != 0 && ( aArrayData[m,"deviceCountFound"] != 0 || aArrayData[m,"deviceCount16"] != 0 ) ) {
+ aArrayData[m,"deviceCount16"]=int(aArrayData[m,"deviceCount16"])
+ ## first check that actual memory found is not greater than listed max cap, or
+ ## checking to see module count * max mod size is not > used capacity
+ if ( aArrayData[m,"usedCapacity"] != 0 && aArrayData[m,"maxCapacity16"] != 0 ) {
+ if ( aArrayData[m,"usedCapacity"] > workingMaxCap ) {
+ if ( aArrayData[m,"maxModuleSize"] != 0 &&
+ aArrayData[m,"usedCapacity"] < aArrayData[m,"deviceCount16"] * aArrayData[m,"maxModuleSize"] ) {
+ workingMaxCap=aArrayData[m,"deviceCount16"] * aArrayData[m,"maxModuleSize"]
+ estCap=" (est)"
+ if ( bDebugger1 == "true" ){
+ print "A"
+ }
+ }
+ else if ( aArrayData[m,"derivedModuleSize"] != 0 &&
+ aArrayData[m,"usedCapacity"] < aArrayData[m,"deviceCount16"] * aArrayData[m,"derivedModuleSize"] ) {
+ workingMaxCap=aArrayData[m,"deviceCount16"] * aArrayData[m,"derivedModuleSize"]
+ estCap=" (est)"
+ if ( bDebugger1 == "true" ){
+ print "B"
+ }
+ }
+ else {
+ workingMaxCap=aArrayData[m,"usedCapacity"]
+ estCap=" (est)"
+ if ( bDebugger1 == "true" ){
+ print "C"
+ }
+ }
+ }
+ }
+ # note that second case will never really activate except on virtual machines and maybe
+ # mobile devices
+ if ( estCap == "" ) {
+ # do not do this for only single modules found, max mod size can be equal to the array size
+ if ( ( aArrayData[m,"deviceCount16"] > 1 && aArrayData[m,"deviceCountFound"] > 1 ) &&
+ ( workingMaxCap < aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCount16"] ) ) {
+ workingMaxCap = aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCount16"]
+ estCap=" (est)"
+ if ( bDebugger1 == "true" ){
+ print "D"
+ }
+ }
+ else if ( ( aArrayData[m,"deviceCountFound"] > 0 ) &&
+ ( workingMaxCap < aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCountFound"] ) ) {
+ workingMaxCap = aArrayData[m,"derivedModuleSize"] * aArrayData[m,"deviceCountFound"]
+ estCap=" (est)"
+ if ( bDebugger1 == "true" ){
+ print "E"
+ }
+ }
+ ## handle cases where we have type 5 data: mms x device count equals type 5 max cap
+ # however do not use it if cap / devices equals the derived module size
+ else if ( aArrayData[m,"maxModuleSize"] > 0 &&
+ ( aArrayData[m,"maxModuleSize"] * aArrayData[m,"deviceCount16"] == aArrayData[m,"maxCapacity5"] ) &&
+ aArrayData[m,"maxCapacity5"] != aArrayData[m,"maxCapacity16"] &&
+ aArrayData[m,"maxCapacity16"] / aArrayData[m,"deviceCount16"] != aArrayData[m,"derivedModuleSize"] ) {
+ workingMaxCap = aArrayData[m,"maxCapacity5"]
+ altCap=aArrayData[m,"maxCapacity5"] # not used
+ estCap=" (check)"
+ if ( bDebugger1 == "true" ){
+ print "F"
+ }
+ }
+ }
+ }
+ altCap=int(altCap)
+ workingMaxCap=int(workingMaxCap)
+ if ( bDebugger1 == "true" ){
+ print "4: mmods: " aArrayData[m,"maxModuleSize"] " :dmmods: " aArrayData[m,"derivedModuleSize"] " :mcap: " workingMaxCap " :ucap: " aArrayData[m,"usedCapacity"]
+ }
+ # some cases of type 5 have too big module max size, just dump the data then since
+ # we cannot know if it is valid or not, and a guess can be wrong easily
+ if ( aArrayData[m,"maxModuleSize"] != 0 && workingMaxCap != "" &&
+ ( aArrayData[m,"maxModuleSize"] > workingMaxCap ) ){
+ aArrayData[m,"maxModuleSize"] = 0
+ # print "yes"
+ }
+ if ( bDebugger1 == "true" ){
+ print "5: dms: " aArrayData[m,"derivedModuleSize"] " :dc: " aArrayData[m,"deviceCount16"] " :wmc: " workingMaxCap
+ }
+ ## prep for output ##
+ if (aArrayData[m,"maxModuleSize"] == 0 ){
+ aArrayData[m,"maxModuleSize"]=""
+ # ie: 2x4gB
+ if ( estCap == "" && int(aArrayData[m,"derivedModuleSize"]) > 0 &&
+ workingMaxCap > ( int(aArrayData[m,"derivedModuleSize"]) * int(aArrayData[m,"deviceCount16"]) * 4 ) ) {
+ estCap=" (check)"
+ if ( bDebugger1 == "true" ){
+ print "G"
+ }
+ }
+ }
+ else {
+ # case where listed max cap is too big for actual slots x max cap, eg:
+ # listed max cap, 8gb, max mod 2gb, slots 2
+ if ( estCap == "" && aArrayData[m,"maxModuleSize"] > 0 ) {
+ if ( int(workingMaxCap) > int(aArrayData[m,"maxModuleSize"]) * aArrayData[m,"deviceCount16"] ) {
+ estCap=" (check)"
+ if ( bDebugger1 == "true" ){
+ print "H"
+ }
+ }
+ }
+ if (aArrayData[m,"maxModuleSize"] > 1023 ) {
+ aArrayData[m,"maxModuleSize"]=aArrayData[m,"maxModuleSize"] / 1024 " GB"
+ }
+ else {
+ aArrayData[m,"maxModuleSize"]=aArrayData[m,"maxModuleSize"] " MB"
+ }
+ }
+ if ( aArrayData[m,"deviceCount16"] == 0 ) {
+ aArrayData[m,"deviceCount16"] = ""
+ }
+ if (workingMaxCap != 0 ) {
+ if ( workingMaxCap < 1024 ) {
+ workingMaxCap = workingMaxCap
+ unit=" MB"
+ }
+ else if ( workingMaxCap < 1024000 ) {
+ workingMaxCap = workingMaxCap / 1024
+ unit=" GB"
+ }
+ else if ( workingMaxCap < 1024000000 ) {
+ workingMaxCap = workingMaxCap / 1024000
+ unit=" TB"
+ }
+ # we only want a max 2 decimal places, this trick gives 0 to 2
+ workingMaxCap=gensub(/([0-9]+\.[0-9][0-9]).*/,"\\1",1,workingMaxCap)
+ workingMaxCap = workingMaxCap unit estCap
+
+ }
+ else {
+ workingMaxCap == ""
+ }
+
+ print aArrayData[m,"data-type"] "," aArrayData[m,"handle"] "," aArrayData[m,"location"] "," workingMaxCap "," aArrayData[m,"deviceCount16"] "," aArrayData[m,"use"] "," aArrayData[m,"errorCorrection"] "," aArrayData[m,"maxModuleSize"] estMod "," aArrayData[m,"voltage5"]
+ # print device rows next
+ for ( j=0;j<=100;j++ ) {
+ if (aMemory[m,j,0] != "" ) {
+ unit=""
+ workingSize=aMemory[m,j,2]
+ if ( workingSize ~ /^[0-9]+$/ ) {
+ workingSize=int(workingSize)
+ if ( workingSize < 1024 ) {
+ workingSize = workingSize
+ unit=" MB"
+ }
+ else if ( workingSize < 1024000 ) {
+ workingSize = workingSize / 1024
+ unit=" GB"
+ }
+ else if ( workingSize < 1024000000 ) {
+ workingSize = workingSize / 1024000
+ unit=" TB"
+ }
+ # we only want a max 2 decimal places, this trick gives 0 to 2
+ workingSize=gensub(/([0-9]+\.[0-9][0-9]).*/,"\\1",1,workingSize)
+ workingSize = workingSize unit
+ }
+ print aMemory[m,j,0] "," aMemory[m,j,1] "," workingSize "," aMemory[m,j,3] "," aMemory[m,j,4] "," aMemory[m,j,5] "," aMemory[m,j,6] "," aMemory[m,j,7] "," aMemory[m,j,8] "," aMemory[m,j,9] "," aMemory[m,j,10] "," aMemory[m,j,11] "," aMemory[m,j,12] "," aMemory[m,j,13] "," aMemory[m,j,14] "," aMemory[m,j,15] "," aMemory[m,j,16] "," aMemory[m,j,17]
+ }
+ else {
+ break
+ }
+ }
+ }
+ }' <<< "$DMIDECODE_DATA" ) )
+ fi
+ fi
+ IFS="$ORIGINAL_IFS"
+ a_temp=${A_MEMORY_DATA[@]}
+
+ # echo "${a_temp[@]}"
+ log_function_data "A_MEMORY_DATA: $a_temp"
+
+ eval $LOGFE
+}
+
+# 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
+# args: $1 - [file location of debug data file - optional, only for debugging data collection]
+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/' ports_conf='/etc/portsnap.conf' openbsd_conf='/etc/pkg.conf'
+ local bsd_pkg_dir='/usr/local/etc/pkg/repos/' slackpkg_file='/etc/slackpkg/mirrors'
+ local netbsd_file='/usr/pkg/etc/pkgin/repositories.conf' freebsd_file='/etc/freebsd-update.conf'
+ local freebsd_pkg_file='/etc/pkg/FreeBSD.conf' slackpkg_plus_file='/etc/slackpkg/slackpkgplus.conf'
+ local portage_repo_dir='/etc/portage/repos.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_files=$(ls /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null)
+ log_function_data "apt repo files: $repo_files"
+ for repo_file in $repo_files
+ do
+ if [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -v repoFile="$repo_file" '
+ !/^[[:space:]]*$|^[[:space:]]*#/ {
+ print "apt sources^" repoFile "^" $0
+ }' $repo_file )"
+ get_repo_builder "$repo_data_working"
+ done
+ repo_data_working=''
+ 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'
+ log_function_data "yum repo files: $repo_files"
+ elif [[ -d $zypp_repo_dir ]];then
+ repo_files=$( ls $zypp_repo_dir*.repo 2>/dev/null )
+ repo_name='zypp'
+ log_function_data "zypp repo files: $repo_files"
+ fi
+ if [[ -n $repo_files ]];then
+ for repo_file in $repo_files
+ do
+ if [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ 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
+ get_repo_builder "$repo_data_working"
+ done
+ fi
+ repo_data_working=''
+ # 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 [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ 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 )"
+ repo_data_working=''
+ # pisi - pardus
+ elif [[ -f $slackpkg_file || -f $slackpkg_plus_file ]];then
+ # note, only one file, but loop it in case more are added in future
+ if [[ -f $slackpkg_file ]];then
+ if [[ -n $1 ]];then
+ cat $slackpkg_file &> $1/repo-data_${slackpkg_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -v repoFile="$slackpkg_file" '
+ !/^[[:space:]]*$|^[[:space:]]*#/ {
+ print "slackpkg sources^" repoFile "^" $0
+ }' $slackpkg_file )"
+ get_repo_builder "$repo_data_working"
+ fi
+ if [[ -f $slackpkg_plus_file ]];then
+ if [[ -n $1 ]];then
+ cat $slackpkg_plus_file &> $1/repo-data_${slackpkg_plus_file//\//-}.txt
+ fi
+ # see sample for syntax
+ repo_data_working="$( gawk -F '=' -v repoFile="$slackpkg_plus_file" '
+ BEGIN {
+ activeRepos=""
+ }
+ # stop if set to off
+ /^SLACKPKGPLUS/ {
+ if ( $2 == "off" ){
+ exit
+ }
+ }
+ # get list of current active repos
+ /^REPOPLUS/ {
+ activeRepos=$2
+ }
+ # print out repo line if found
+ /^MIRRORPLUS/ {
+ if ( activeRepos != "" ) {
+ gsub(/MIRRORPLUS\['\''|'\''\]/,"",$1)
+ if ( match( activeRepos, $1 ) ){
+ print "slackpkg+ sources^" repoFile "^" $1 " ~ " $2
+ }
+ }
+ }' $slackpkg_plus_file )"
+ get_repo_builder "$repo_data_working"
+ fi
+ repo_data_working=''
+ elif [[ -d $portage_repo_dir && -n $( type -p emerge ) ]];then
+ repo_files=$( ls $portage_repo_dir*.conf 2>/dev/null )
+ repo_name='portage'
+ log_function_data "portage repo files: $repo_files"
+ if [[ -n $repo_files ]];then
+ for repo_file in $repo_files
+ do
+ if [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ 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 " ~ "
+ }
+ /^(sync-uri)/ {
+ sub( /sync-uri[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
+ urlData = $1
+ }
+ # note: enabled = 1. enabled = 0 means disabled
+ /^auto-sync[[:space:]]*=/ {
+ sub( /auto-sync[[:space:]]*=[[:space:]]*/, "", $1 ) # strip out the field starter
+ 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
+ get_repo_builder "$repo_data_working"
+ done
+ fi
+ elif [[ -d $pisi_dir && -n $( type -p pisi ) ]];then
+ REPO_DATA="$( pisi list-repo )"
+ if [[ -n $1 ]];then
+ echo "$REPO_DATA" &> $1/repo-data_pisi-list-repo.txt
+ fi
+ log_function_data "pisi-list-repo: $REPO_DATA"
+ # 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 )"
+ repo_data_working=''
+ # Mandriva/Mageia using: urpmq
+ elif type -p urpmq &>/dev/null;then
+ REPO_DATA="$( urpmq --list-media active --list-url )"
+ if [[ -n $1 ]];then
+ echo "$REPO_DATA" &> $1/repo-data_urpmq-list-media-active.txt
+ fi
+ # 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 $ports_conf || -f $freebsd_file || -d $bsd_pkg_dir ]];then
+ if [[ -f $ports_conf ]];then
+ if [[ -n $1 ]];then
+ cat $ports_conf &> $1/repo-data_${ports_conf//\//-}.txt
+ fi
+ repo_data_working="$( gawk -F '=' -v repoFile=$ports_conf '
+ BEGIN {
+ IGNORECASE=1
+ }
+ /^SERVERNAME/ {
+ print "BSD ports server^" repoFile "^" $2
+ exit
+ }
+ ' $ports_conf )"
+ get_repo_builder "$repo_data_working"
+ fi
+ if [[ -f $freebsd_file ]];then
+ if [[ -n $1 ]];then
+ cat $freebsd_file &> $1/repo-data_${freebsd_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -v repoFile=$freebsd_file '
+ BEGIN {
+ IGNORECASE=1
+ }
+ /^ServerName/ {
+ print "FreeBSD update server^" repoFile "^" $2
+ exit
+ }
+ ' $freebsd_file )"
+ get_repo_builder "$repo_data_working"
+ fi
+ if [[ -f $freebsd_pkg_file ]];then
+ if [[ -n $1 ]];then
+ cat $freebsd_pkg_file &> $1/repo-data_${freebsd_pkg_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -F ': ' -v repoFile=$freebsd_pkg_file '
+ BEGIN {
+ IGNORECASE=1
+ }
+ $1 ~ /^[[:space:]]*url/ {
+ gsub(/\"|pkg\+|,/,"",$2)
+ print "FreeBSD default pkg server^" repoFile "^" $2
+ exit
+ }
+ ' $freebsd_pkg_file )"
+ get_repo_builder "$repo_data_working"
+ fi
+
+ if [[ -d $bsd_pkg_dir ]];then
+ repo_files=$(ls ${bsd_pkg_dir}*.conf 2>/dev/null )
+ for repo_file in $repo_files
+ do
+ if [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -v repoFile=$repo_file '
+ BEGIN {
+ FS=":"
+ IGNORECASE=1
+ repoName=""
+ repoUrl=""
+ enabled=""
+ }
+ {
+ gsub(/{|}|^#.*/,"",$0)
+ }
+ /^[^[:space:]]/ {
+ repoName=$1
+ repoUrl=""
+ enabled=""
+ while ( getline && $0 !~ /^[[:space:]]*$/ ) {
+ gsub(/'"$BAN_LIST_ARRAY"'/,"",$0)
+ gsub(/({|}|^[[:space:]]+|[[:space:]]+$)/,"",$1)
+ gsub(/({|}|^[[:space:]]+|[[:space:]]+$)/,"",$2)
+ if ( $1 == "url" ) {
+ repoUrl=$2$3
+ }
+ if ( $1 == "enabled" ) {
+ if ( $2 == "yes" ) {
+ print "BSD pkg server^" repoFile "^" repoName " ~ " repoUrl
+ }
+ }
+ }
+ }
+ ' $repo_file )"
+ get_repo_builder "$repo_data_working"
+ done
+ fi
+ repo_data_working=''
+ elif [[ -f $openbsd_conf ]];then
+ if [[ -n $1 ]];then
+ cat $openbsd_conf &> $1/repo-data_${openbsd_conf//\//-}.txt
+ fi
+ REPO_DATA="$( gawk -F '=' -v repoFile=$openbsd_conf '
+ BEGIN {
+ IGNORECASE=1
+ }
+ /^installpath/ {
+ print "OpenBSD pkg mirror^" repoFile "^" $2
+ }
+ ' $openbsd_conf )"
+ elif [[ -f $netbsd_file ]];then
+ # note, only one file, but loop it in case more are added in future
+ for repo_file in $netbsd_file
+ do
+ if [[ -n $1 ]];then
+ cat $repo_file &> $1/repo-data_${repo_file//\//-}.txt
+ fi
+ repo_data_working="$( gawk -v repoFile="$repo_file" '
+ !/^[[:space:]]*$|^[[:space:]]*#/ {
+ print "NetBSD pkg servers^" repoFile "^" $0
+ }' $repo_file )"
+ get_repo_builder "$repo_data_working"
+ done
+ repo_data_working=''
+ fi
+ eval $LOGFE
+}
+# build the total REPO_DATA global here
+# args: $1 - the repo line/s
+get_repo_builder()
+{
+ if [[ -n $1 ]];then
+ if [[ -z $REPO_DATA ]];then
+ REPO_DATA="$1"
+ else
+ REPO_DATA="$REPO_DATA
+$1"
+ fi
+ fi
+}
+
+get_runlevel_data()
+{
+ eval $LOGFS
+ local runlvl=''
+
+ if type -p runlevel &>/dev/null;then
+ runlvl="$( runlevel | 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=${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 a_temp=''
+
+ 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="" # these only if all else fails...
+ cpuPeciTemp="" # use if temps are missing or wrong
+ cpuTemp=""
+ cpuTempReal=""
+ fanWorking=""
+ indexCountaFanMain=0
+ indexCountaFanDefault=0
+ i=""
+ j=""
+ moboTemp=""
+ moboTempReal=""
+ psuTemp=""
+ separator=""
+ sysFanString=""
+ temp1=""
+ temp2=""
+ temp3=""
+ tempDiff=20 # for C, handled for F after that is determined
+ 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
+ }
+ }
+ # issue 58 msi/asus show wrong for CPUTIN so overwrite it if PECI 0 is present
+ # http://www.spinics.net/lists/lm-sensors/msg37308.html
+ /^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
+ }
+ }
+ /^PECI[[:space:]]Agent[[:space:]]0(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ cpuPeciTemp=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
+ }
+ }
+ # for temp1/2 only use temp1/2 if they are null or greater than the last ones
+ $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( temp1 == "" || ( tempWorking != "" && 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 != "" && tempWorking > 0 ) ) {
+ temp2=tempWorking
+ }
+ tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 )
+ if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){
+ tempUnit=tempWorkingUnit
+ }
+ }
+ # temp3 is only used as an absolute override for systems with all 3 present
+ $1 ~ /^temp3$/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( temp3 == "" || ( tempWorking != "" && tempWorking > 0 ) ) {
+ temp3=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|Physical id 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ {
+ tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 )
+ if ( tempWorking != "" && 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
+ # this is wrong for systems with > 2 tempX readings, but the logic is too complex with 3 variables
+ # so have to accept that it will be wrong in some cases, particularly for motherboard temp readings.
+ 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
+ }
+ }
+ # convert the diff number for F, it needs to be bigger that is
+ if ( tempUnit == "F" ) {
+ tempDiff = tempDiff * 1.8
+ }
+ if ( cpuTemp != "" ) {
+ # specific hack to handle broken CPUTIN temps with PECI
+ if ( cpuPeciTemp != "" && ( cpuTemp - cpuPeciTemp ) > tempDiff ){
+ cpuTempReal=cpuPeciTemp
+ }
+ # then get the real cpu temp, best guess is hottest is real
+ else {
+ cpuTempReal=cpuTemp
+ }
+ }
+ else {
+ if ( tempFanType != "" ){
+ # there are some weird scenarios
+ if ( tempFanType == 1 ){
+ if ( temp1 != "" && temp2 != "" && temp2 > temp1 ) {
+ cpuTempReal=temp2
+ }
+ else {
+ cpuTempReal=temp1
+ }
+ }
+ else {
+ if ( temp1 != "" && temp2 != "" && temp1 > temp2 ) {
+ cpuTempReal=temp1
+ }
+ else {
+ cpuTempReal=temp2
+ }
+ }
+ }
+ else {
+ cpuTempReal=temp1 # can be null, that is ok
+ }
+ if ( cpuTempReal != "" ) {
+ # using temp3 is just not reliable enough, more errors caused than fixed imo
+ #if ( temp3 != "" && temp3 > cpuTempReal ) {
+ # cpuTempReal=temp3
+ #}
+ # there are some absurdly wrong temp1: acpitz-virtual-0 temp1: +13.8°C
+ if ( core0Temp != "" && (core0Temp - cpuTempReal) > tempDiff ) {
+ cpuTempReal=core0Temp
+ }
+ }
+ }
+ # if all else fails, use core0/peci temp if present and cpu is null
+ if ( cpuTempReal == "" ) {
+ if ( core0Temp != "" ) {
+ cpuTempReal=core0Temp
+ }
+ # note that peci temp is known to be colder than the actual system
+ # sometimes so it is the last fallback we want to use even though in theory
+ # it is more accurate, but fact suggests theory wrong.
+ else if ( cpuPeciTemp != "" ) {
+ cpuTempReal=cpuPeciTemp
+ }
+ }
+ # then the real mobo temp
+ if ( moboTemp != "" ){
+ moboTempReal=moboTemp
+ }
+ else if ( tempFanType != "" ){
+ if ( tempFanType == 1 ) {
+ if ( temp1 != "" && temp2 != "" && temp2 > temp1 ) {
+ moboTempReal=temp1
+ }
+ else {
+ moboTempReal=temp2
+ }
+ }
+ else {
+ if ( temp1 != "" && temp2 != "" && temp1 > temp2 ) {
+ moboTempReal=temp2
+ }
+ else {
+ moboTempReal=temp1
+ }
+ }
+ ## NOTE: not safe to assume temp3 is the mobo temp, sad to say
+ #if ( temp1 != "" && temp2 != "" && temp3 != "" && temp3 < moboTempReal ) {
+ # moboTempReal= temp3
+ #}
+ }
+ 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"
+ a_temp=${A_SENSORS_DATA[@]}
+ log_function_data "A_SENSORS_DATA: $a_temp"
+# echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}"
+ eval $LOGFE
+}
+
+get_sensors_output()
+{
+ local sensors_data=''
+
+ if type -p sensors &>/dev/null;then
+ sensors_data="$( sensors 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_program_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_program_version "$shell_type" "^tcsh" "2" )
+ ;;
+ dash)
+ shell_version=$( get_program_version "$shell_type" "$shell_type" "3" )
+ ;;
+ ksh)
+ shell_version=$( get_program_version "$shell_type" "version" "5" )
+ ;;
+ tcsh)
+ shell_version=$( get_program_version "$shell_type" "^tcsh" "2" )
+ ;;
+ zsh)
+ shell_version=$( get_program_version "$shell_type" "^zsh" "2" )
+ ;;
+ esac
+ fi
+ if [[ -n $shell_version ]];then
+ shell_type="$shell_type $shell_version"
+ fi
+ echo $shell_type
+ log_function_data "shell type: $shell_type"
+ eval $LOGFE
+}
+
+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
+ # darwin sysctl has BOTH = and : separators, and repeats data. Why? No bsd discipline, that's for sure
+ if [[ $BSD_VERSION == 'darwin' ]];then
+ sysctl_data="$( sysctl -$1 | sed 's/[[:space:]]*=[[:space:]]*/: /' )"
+ else
+ sysctl_data="$( sysctl -$1 )"
+ fi
+ 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=$( tty 2>/dev/null | sed 's/[^0-9]*//g' )
+ tty_number=${tty_number##*/}
+ 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
+ local uptime_value=''
+ ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a
+ if type -p uptime &>/dev/null;then
+ uptime_value="$( uptime | gawk '{
+ a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0)
+ print a
+ }' )"
+ fi
+ 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='' downloader_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='' a_temp=''
+
+ # 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
+ case $DOWNLOADER in
+ curl)
+ location_data="$( curl -y $DL_TIMEOUT -s $location_site )" || downloader_error=$?
+ ;;
+ fetch)
+ location_data="$( fetch -T $DL_TIMEOUT -q -o - $location_site )" || downloader_error=$?
+ ;;
+ ftp)
+ location_data="$( ftp -o - $location_site 2>/dev/null )" || downloader_error=$?
+ ;;
+ wget)
+ location_data="$( wget -t 1 -T $DL_TIMEOUT -q -O - $location_site )" || downloader_error=$?
+ ;;
+ no-downloader)
+ downloader_error=100
+ ;;
+ esac
+ log_function_data "$location_data"
+
+ if [[ $downloader_error -ne 0 ]];then
+ if [[ $downloader_error -eq 100 ]];then
+ data_grab_error="Error: No downloader tool available. Install wget, curl, or fetch."
+ else
+ data_grab_error="Error: location server up but download error - $DOWNLOADER: $downloader_error"
+ fi
+ fi
+ downloader_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
+ case $DOWNLOADER in
+ curl)
+ weather_data="$( curl -y $DL_TIMEOUT -s $weather_feed"$location" )" || downloader_error=$?
+ ;;
+ fetch)
+ weather_data="$( fetch -T $DL_TIMEOUT -q -o - $weather_feed"$location" )" || downloader_error=$?
+ ;;
+ ftp)
+ weather_data="$( ftp -o - $weather_feed"$location" 2>/dev/null )" || downloader_error=$?
+ ;;
+ wget)
+ weather_data="$( wget -t 1 -T $DL_TIMEOUT -q -O - $weather_feed"$location" )" || downloader_error=$?
+ ;;
+ no-downloader)
+ downloader_error=100
+ ;;
+ esac
+ if [[ $downloader_error -ne 0 ]];then
+ if [[ $downloader_error -eq 100 ]];then
+ data_grab_error="Error: No downloader tool available. Install wget, curl, or fetch."
+ else
+ data_grab_error="Error: weather server up but download error - $DOWNLOADER: $downloader_error"
+ fi
+ 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
+ a_temp=${A_WEATHER_DATA[@]}
+ log_function_data "A_WEATHER_DATA: $a_temp"
+
+ 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
+# note; this cleanup may not be working on bsd sed
+calculate_line_length()
+{
+ local string=$1
+ # ansi: \e[1;34m irc: \x0312
+ # note: using special trick for bsd sed, tr - NOTE irc sed must use " double quote
+ string=$( sed -e 's/'$ESC'\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' -e "s/\\\x0[0-9]\{1,3\}//g" <<< $string )
+ 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=$( 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
+ }' <<< "$cpu_flags_working" )
+
+ #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
+}
+
+#### -------------------------------------------------------------------
+#### print and processing of output data
+#### -------------------------------------------------------------------
+
+#### MASTER PRINT FUNCTION - triggers all line item print functions
+## main function to print out, master for all sub print functions.
+print_it_out()
+{
+ eval $LOGFS
+ # note that print_it_out passes local variable values on to its children,
+ # and in some cases, their children, with Lspci_v_Data
+ local Lspci_v_Data='' Lspci_n_Data='' # only for verbose
+ local Sysctl_a_Data='' Dmesg_Boot_Data=''
+
+ if [[ -n $BSD_TYPE ]];then
+ Sysctl_a_Data="$( get_sysctl_data 'a' )"
+ Dmesg_Boot_Data="$( get_dmesg_boot_data )"
+ fi
+
+ if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then
+ print_short_data
+ else
+ Lspci_v_Data="$( get_lspci_data 'v' )"
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
+ Lspci_n_Data="$( get_lspci_data 'n' )"
+ fi
+ if [[ $B_SHOW_SYSTEM == 'true' ]];then
+ print_system_data
+ fi
+ if [[ $B_SHOW_MACHINE == 'true' ]];then
+ print_machine_data
+ fi
+ if [[ $B_SHOW_BATTERY == 'true' ]];then
+ print_battery_data
+ fi
+ if [[ $B_SHOW_BASIC_CPU == 'true' || $B_SHOW_CPU == 'true' ]];then
+ print_cpu_data
+ fi
+ if [[ $B_SHOW_MEMORY == 'true' ]];then
+ print_ram_data
+ fi
+ if [[ $B_SHOW_GRAPHICS == 'true' ]];then
+ print_graphics_data
+ fi
+ if [[ $B_SHOW_AUDIO == 'true' ]];then
+ print_audio_data
+ fi
+ if [[ $B_SHOW_NETWORK == 'true' ]];then
+ print_networking_data
+ fi
+ if [[ $B_SHOW_DISK_TOTAL == 'true' || $B_SHOW_BASIC_DISK == 'true' || $B_SHOW_DISK == 'true' ]];then
+ print_hard_disk_data
+ fi
+ if [[ $B_SHOW_PARTITIONS == 'true' ]];then
+ print_partition_data
+ fi
+ if [[ $B_SHOW_RAID == 'true' || $B_SHOW_BASIC_RAID == 'true' ]];then
+ print_raid_data
+ fi
+ if [[ $B_SHOW_UNMOUNTED_PARTITIONS == 'true' ]];then
+ print_unmounted_partition_data
+ fi
+ if [[ $B_SHOW_SENSORS == 'true' ]];then
+ print_sensors_data
+ fi
+ if [[ $B_SHOW_REPOS == 'true' ]];then
+ print_repo_data
+ fi
+ if [[ $B_SHOW_PS_CPU_DATA == 'true' || $B_SHOW_PS_MEM_DATA == 'true' ]];then
+ print_ps_data
+ fi
+ if [[ $B_SHOW_WEATHER == 'true' ]];then
+ print_weather_data
+ fi
+ if [[ $B_SHOW_INFO == 'true' ]];then
+ print_info_data
+ fi
+ fi
+ ## last steps, clear any lingering colors
+ if [[ $B_IRC == 'false' && $SCHEME -gt 0 ]];then
+ echo -n "\e[0m"
+ fi
+
+ eval $LOGFE
+}
+
+#### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0
+# all the get data stuff is loaded here to keep execution time down for single line print commands
+# these will also be loaded in each relevant print function for long output
+print_short_data()
+{
+ eval $LOGFS
+ local current_kernel=$( get_kernel_version )
+ local processes=$(( $( wc -l <<< "$Ps_aux_Data" ) - 1 ))
+ local short_data='' i='' b_background_black='false'
+ local memory=$( get_memory_data )
+ local up_time="$( get_uptime )"
+ if [[ -z $up_time ]];then
+ up_time='N/A - missing uptime?'
+ fi
+
+ # set A_CPU_CORE_DATA
+ get_cpu_core_count
+ local cpc_plural='' cpu_count_print='' model_plural='' current_max_clock=''
+ local cpu_physical_count=${A_CPU_CORE_DATA[0]}
+ local cpu_core_count=${A_CPU_CORE_DATA[3]}
+ local cpu_core_alpha=${A_CPU_CORE_DATA[1]}
+ local cpu_type=${A_CPU_CORE_DATA[2]}
+ local kernel_os='' speed_starter='speed'
+ local cpu_data_string=''
+
+ if [[ -z $BSD_TYPE || -n $cpu_type ]];then
+ cpu_type=" ($cpu_type)"
+ fi
+
+ if [[ $BSD_TYPE == 'bsd' ]];then
+ kernel_os="${C1}OS${C2}$SEP1$( uname -rsp )"
+ else
+ kernel_os="${C1}Kernel${C2}$SEP1$current_kernel"
+ fi
+
+ if [[ $cpu_physical_count -gt 1 ]];then
+ cpc_plural='(s)'
+ model_plural='s'
+ cpu_count_print="$cpu_physical_count "
+ # for multicpu systems, divide total cores by cpu count to get per cpu cores
+ $cpu_core_count=$(($cpu_core_count/$cpu_physical_count))
+ fi
+ if [[ -z $BSD_TYPE ]];then
+ cpu_data_string="$cpu_count_print$cpu_core_alpha core"
+ else
+ cpu_data_string="$cpu_count_print$cpu_core_count core"
+ fi
+# local cpu_core_count=${A_CPU_CORE_DATA[0]}
+
+ # load A_HDD_DATA
+ get_hdd_data_basic
+ ## note: if hdd_model is declared prior to use, whatever string you want inserted will
+ ## be inserted first. In this case, it's desirable to print out (x) before each disk found.
+ local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 ))
+ IFS=","
+ local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} )
+ IFS="$ORIGINAL_IFS"
+ local hdd_capacity=${a_hdd_basic_working[0]}
+ local hdd_used=${a_hdd_basic_working[1]}
+
+ # load A_CPU_DATA
+ get_cpu_data
+
+ IFS=","
+ local a_cpu_working=(${A_CPU_DATA[0]})
+ # this gets that weird min/max final array item, which almost never contains any data of use
+ local current_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
+ local a_cpu_speeds=(${A_CPU_DATA[$current_max_clock_nu]})
+ IFS="$ORIGINAL_IFS"
+ local cpu_model="${a_cpu_working[0]}"
+ ## assemble data for output
+ local cpu_clock="${a_cpu_working[1]}" # old CPU3
+ # echo $cpu_clock
+ # if [[ -z ${a_cpu_working[1]} || ${a_cpu_working[1]} < 50 ]];then
+ # a_cpu_working[1]=$(get_cpu_speed_hack)
+ # fi
+
+ # this handles the case of for example ARM cpus, which will not have data for
+ # min/max, since they don't have speed. Since that sets a flag, not found, just
+ # look for that and use the speed from the first array array, same where we got
+ # model from
+ # index: 0 speed ; 1 min ; 2 max
+ # this handles bsd types which always should show N/A unless we get a way to get min / max data
+ if [[ "${a_cpu_speeds[0]}" == 'N/A' && ${a_cpu_working[1]} != '' ]];then
+ current_max_clock="${a_cpu_working[1]} MHz"
+ else
+ if [[ ${a_cpu_speeds[2]} != 0 ]];then
+ if [[ ${a_cpu_speeds[0]} == ${a_cpu_speeds[2]} ]];then
+ current_max_clock="${a_cpu_speeds[0]} MHz (max)"
+ else
+ current_max_clock="${a_cpu_speeds[0]}/${a_cpu_speeds[2]} MHz"
+ speed_starter='speed/max'
+ fi
+ fi
+ fi
+ local patch_version_number=$( get_patch_version_string )
+
+ #set_color_scheme 12
+ if [[ $B_IRC == 'true' ]];then
+ for i in $C1 $C2 $CN
+ do
+ case "$i" in
+ "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN")
+ b_background_black='true'
+ ;;
+ esac
+ done
+ if [[ $b_background_black == 'true' ]];then
+ for i in C1 C2 CN
+ do
+ ## these need to be in quotes, don't know why
+ if [[ ${!i} == $NORMAL ]];then
+ declare $i="${!i}15,1"
+ else
+ declare $i="${!i},1"
+ fi
+ done
+ #C1="${C1},1"; C2="${C2},1"; CN="${CN},1"
+ fi
+ fi
+ short_data="${C1}CPU$cpc_plural${C2}$SEP1$cpu_data_string $cpu_model$model_plural$cpu_type ${C1}$speed_starter${C2}$SEP1$current_max_clock$SEP2$kernel_os$SEP2${C1}Up${C2}$SEP1$up_time$SEP2${C1}Mem${C2}$SEP1$memory$SEP2${C1}HDD${C2}$SEP1$hdd_capacity($hdd_used)$SEP2${C1}Procs${C2}$SEP1$processes$SEP2"
+
+ if [[ $SHOW_IRC -gt 0 ]];then
+ short_data="$short_data${C1}Client${C2}$SEP1$IRC_CLIENT$IRC_CLIENT_VERSION$SEP2"
+ fi
+ short_data="$short_data${C1}$SCRIPT_NAME${C2}$SEP1$SCRIPT_VERSION_NUMBER$patch_version_number$SEP2${CN}"
+ if [[ $SCHEME -gt 0 ]];then
+ short_data="$short_data $NORMAL"
+ fi
+ print_screen_output "$short_data"
+ eval $LOGFE
+}
+
+#### LINE ITEM PRINT FUNCTIONS
+
+# print sound card data
+print_audio_data()
+{
+ eval $LOGFS
+ local i='' card_id='' audio_data='' a_audio_data='' port_data='' pci_bus_id='' card_string=''
+ local a_audio_working='' audio_driver='' alsa_data='' port_plural='' module_version='' chip_id=''
+ local bus_usb_text='' bus_usb_id='' line_starter='Audio:' alsa='' alsa_version='' print_data=''
+ local driver=''
+ # set A_AUDIO_DATA and get alsa data
+ if [[ $BSD_TYPE == 'bsd' ]];then
+ if [[ $B_PCICONF == 'true' ]];then
+ if [[ $B_PCICONF_SET == 'false' ]];then
+ get_pciconf_data
+ fi
+ get_pciconf_card_data 'audio'
+ elif [[ $B_LSPCI == 'true' ]];then
+ get_audio_data
+ fi
+ else
+ get_audio_data
+ fi
+
+ get_audio_alsa_data
+ # alsa driver data now prints out no matter what
+ if [[ -n $A_ALSA_DATA ]];then
+ IFS=","
+ if [[ -n ${A_ALSA_DATA[0]} ]];then
+ alsa=${A_ALSA_DATA[0]}
+ else
+ alsa='N/A'
+ fi
+ if [[ -n ${A_ALSA_DATA[1]} ]];then
+ alsa_version=${A_ALSA_DATA[1]}
+ else
+ alsa_version='N/A'
+ fi
+ alsa_data="${C1}Sound$SEP3${C2} $alsa ${C1}v$SEP3${C2} $alsa_version"
+ IFS="$ORIGINAL_IFS"
+ fi
+ # note, error handling is done in the get function, so this will never be null, but
+ # leaving the test just in case it's changed.
+ if [[ -n ${A_AUDIO_DATA[@]} ]];then
+ for (( i=0; i< ${#A_AUDIO_DATA[@]}; i++ ))
+ do
+ IFS=","
+ a_audio_working=( ${A_AUDIO_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+ port_data=''
+ audio_driver=''
+ audio_data=''
+ card_string=''
+ port_plural=''
+ module_version=''
+ pci_bus_id=''
+ bus_usb_text=''
+ bus_usb_id=''
+ print_data=''
+ chip_id=''
+
+ if [[ ${#A_AUDIO_DATA[@]} -gt 1 ]];then
+ card_id="-$(( $i + 1 ))"
+ fi
+ if [[ $BSD_TYPE != 'bsd' ]];then
+ if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then
+ module_version=$( print_module_version "${a_audio_working[3]}" 'audio' )
+ elif [[ -n ${a_audio_working[1]} && $B_EXTRA_DATA == 'true' ]];then
+ module_version=$( print_module_version "${a_audio_working[1]}" 'audio' )
+ fi
+ fi
+ # we're testing for the presence of the 2nd array item here, which is the driver name
+ if [[ -n ${a_audio_working[1]} ]];then
+ # note: linux drivers can have numbers, like tg3
+ if [[ $BSD_TYPE == 'bsd' ]];then
+ driver=$( sed 's/[0-9]$//' <<< ${a_audio_working[1]} )
+ else
+ driver=${a_audio_working[1]}
+ fi
+ audio_driver="${C1}driver$SEP3${C2} $driver "
+ fi
+ if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then
+ if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then
+ port_plural='s'
+ fi
+ port_data="${C1}port$port_plural$SEP3${C2} ${a_audio_working[2]} "
+ fi
+ if [[ -n ${a_audio_working[4]} && $B_EXTRA_DATA == 'true' ]];then
+ if [[ ${a_audio_working[1]} != 'USB Audio' ]];then
+ bus_usb_text='bus-ID'
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
+ if [[ $BSD_TYPE != 'bsd' ]];then
+ chip_id=$( get_lspci_chip_id "${a_audio_working[4]}" )
+ else
+ chip_id=${a_audio_working[6]}
+ fi
+ fi
+ else
+ bus_usb_text='usb-ID'
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
+ chip_id=${a_audio_working[5]}
+ fi
+ fi
+ bus_usb_id=${a_audio_working[4]}
+ pci_bus_id="${C1}$bus_usb_text$SEP3${C2} $bus_usb_id "
+ if [[ -n $chip_id ]];then
+ chip_id="${C1}chip-ID$SEP3${C2} $chip_id "
+ fi
+ fi
+ if [[ -n ${a_audio_working[0]} ]];then
+ card_string="${C1}Card$card_id$EP3${C2} ${a_audio_working[0]} "
+ audio_data="$audio_driver$port_data$pci_bus_id$chip_id"
+ fi
+ # only print alsa on last line if short enough, otherwise print on its own line
+ if [[ $i -eq 0 ]];then
+ if [[ -n $alsa_data && $( calculate_line_length "$card_string$audio_data$alsa_data" ) -lt $COLS_INNER ]];then
+ audio_data="$audio_data$alsa_data"
+ alsa_data=''
+ fi
+ fi
+ if [[ -n $audio_data ]];then
+ if [[ $( calculate_line_length "$card_string$audio_data" ) -lt $COLS_INNER ]];then
+ print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
+ print_screen_output "$print_data"
+ # print the line
+ else
+ # keep the driver on the same line no matter what, looks weird alone on its own line
+ if [[ $( calculate_line_length "$card_string$audio_data" ) -gt $COLS_INNER ]];then
+ print_data=$( create_print_line "$line_starter" "$card_string" )
+ print_screen_output "$print_data"
+ line_starter=' '
+ print_data=$( create_print_line "$line_starter" "$audio_data" )
+ print_screen_output "$print_data"
+ else
+ print_data=$( create_print_line "$line_starter" "$card_string$audio_data" )
+ print_screen_output "$print_data"
+ fi
+ fi
+ line_starter=' '
+ fi
+ done
+ fi
+ if [[ -n $alsa_data ]];then
+ if [[ $( calculate_line_length "${alsa_data/ALSA/Advanced Linux Sound Architecture}" ) -lt $COLS_INNER ]];then
+ # alsa_data=$( sed 's/ALSA/Advanced Linux Sound Architecture/' <<< $alsa_data )
+ alsa_data=${alsa_data/ALSA/Advanced Linux Sound Architecture}
+ fi
+ alsa_data=$( create_print_line "$line_starter" "$alsa_data" )
+ print_screen_output "$alsa_data"
+ fi
+ eval $LOGFE
+}
+
+print_battery_data()
+{
+ eval $LOGFS
+ local line_starter='Battery' print_data=''
+ get_battery_data
+ if [[ -n ${A_BATTERY_DATA[@]} ]];then
+ local battery_data='' battery_string=''
+ local present='' chemistry='' cycles='' voltage_min_design='' voltage_now=''
+ local power_now='' charge_full_design='' charge_full='' charge_now='' capacity=''
+ local capacity_level='' model='' company='' serial='' of_orig='' model='' condition=''
+ local power=''
+
+ # echo ${A_BATTERY_DATA[@]}
+ for (( i=0; i< ${#A_BATTERY_DATA[@]}; i++ ))
+ do
+ battery_data=''
+ print_data=''
+ battery_string=''
+ charge=''
+ model=''
+ condition=''
+ voltage=''
+
+ name=''
+ status=''
+ present=''
+ chemistry=''
+ cycles=''
+ voltage_min_design=''
+ voltage_now=''
+ power_now=''
+ charge_full_design=''
+ charge_full=''
+ charge_now=''
+ capacity=''
+ capacity_level=''
+ of_orig=''
+ model=''
+ company=''
+ serial=''
+ location='' # dmidecode only
+ IFS=","
+ a_battery_working=( ${A_BATTERY_DATA[i]} )
+ IFS="$ORIGINAL_IFS"
+ bat_id="$(( $i + 1 ))"
+
+ if [[ -n ${a_battery_working[10]} ]];then
+ charge="${a_battery_working[10]} Wh "
+ fi
+ if [[ -n ${a_battery_working[11]} ]];then
+ charge="$charge${a_battery_working[11]} "
+ fi
+ if [[ $charge == '' ]];then
+ charge='N/A '
+ fi
+ charge="${C1}charge$SEP3${C2} $charge"
+ if [[ -n ${a_battery_working[9]} ]];then
+ condition="${a_battery_working[9]}"
+ else
+ condition='NA'
+ fi
+ if [[ -n ${a_battery_working[8]} ]];then
+ condition="$condition/${a_battery_working[8]} Wh "
+ else
+ condition="$condition/NA Wh "
+ fi
+ if [[ -n ${a_battery_working[13]} ]];then
+ condition="$condition(${a_battery_working[13]}) "
+ fi
+ if [[ $condition == '' ]];then
+ condition='N/A '
+ fi
+ condition="${C1}condition$SEP3${C2} $condition"
+ if [[ $B_EXTRA_DATA == 'true' ]];then
+ if [[ -n ${a_battery_working[15]} ]];then
+ model="${a_battery_working[15]} "
+ fi
+ if [[ -n ${a_battery_working[14]} ]];then
+ model="$model${a_battery_working[14]} "
+ fi
+ if [[ $model == '' ]];then
+ model='N/A '
+ fi
+ model="${C1}model$SEP3${C2} $model"
+
+ if [[ -n ${a_battery_working[1]} ]];then
+ status="${a_battery_working[1]} "
+ else
+ status="N/A "
+ fi
+ status="${C1}status$SEP3${C2} $status"
+ fi
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' ]];then
+ if [[ -n ${a_battery_working[16]} ]];then
+ serial="${a_battery_working[16]} "
+ else
+ serial='N/A '
+ fi
+ serial="${C1}serial$SEP3${C2} $serial"
+ if [[ -n ${a_battery_working[6]} ]];then
+ voltage="${a_battery_working[6]}"
+ fi
+ if [[ -n ${a_battery_working[5]} ]];then
+ if [[ $voltage == '' ]];then
+ voltage='NA'
+ fi
+ voltage="$voltage/${a_battery_working[5]} "
+ fi
+ if [[ $voltage == '' ]];then
+ voltage='NA '
+ fi
+ voltage="${C1}volts$SEP3${C2} $voltage"
+ fi
+ if [[ $B_EXTRA_EXTRA_EXTRA_DATA == 'true' ]];then
+ if [[ -n ${a_battery_working[3]} ]];then
+ chemistry="${a_battery_working[3]} "
+ fi
+ if [[ -n ${a_battery_working[4]} ]];then
+ cycles="${C1}cycles$SEP3${C2} ${a_battery_working[4]} "
+ fi
+ # location is dmidecode only
+ if [[ -n ${a_battery_working[17]} ]];then
+ location="${C1}loc$SEP3${C2} ${a_battery_working[17]} "
+ fi
+ fi
+ if [[ -n ${a_battery_working[15]} ]];then
+ battery_string="${C1}${a_battery_working[0]}$SEP3${C2} $charge$condition"
+ battery_data="$model$chemistry$serial$status$cycles$location"
+ fi
+
+ if [[ ${A_BATTERY_DATA[0]} == 'dmidecode-error-'* ]];then
+ error_string=$( print_dmidecode_error 'bat' "${A_BATTERY_DATA[0]}" )
+ battery_string=${C2}$error_string
+ battery_data=''
+ voltage=''
+ fi
+
+ if [[ -n $battery_string ]];then
+ if [[ $( calculate_line_length "$battery_string$voltage$battery_data" ) -lt $COLS_INNER ]];then
+ #echo one
+ print_data=$( create_print_line "$line_starter" "$battery_string$voltage$battery_data" )
+ print_screen_output "$print_data"
+ # print the line
+ else
+ # keep the driver on the same line no matter what, looks weird alone on its own line
+ if [[ $( calculate_line_length "$battery_string$voltage$battery_data" ) -gt $COLS_INNER ]];then
+ if [[ $( calculate_line_length "$battery_string$voltage" ) -gt $COLS_INNER ]];then
+ print_data=$( create_print_line "$line_starter" "$battery_string" )
+ print_screen_output "$print_data"
+ line_starter=' '
+ battery_string=''
+ print_data=$( create_print_line "$line_starter" "$voltage" )
+ print_screen_output "$print_data"
+ voltage=''
+ else
+ print_data=$( create_print_line "$line_starter" "$battery_string$voltage" )
+ print_screen_output "$print_data"
+ line_starter=' '
+ voltage=''
+ battery_string=''
+ fi
+ #echo two
+ if [[ $battery_data != '' ]];then
+ print_data=$( create_print_line "$line_starter" "$battery_data" )
+ print_screen_output "$print_data"
+ fi
+ else
+ #echo three
+ print_data=$( create_print_line "$line_starter" "$battery_string$voltage$battery_data" )
+ print_screen_output "$print_data"
+ fi
+ fi
+ line_starter=' '
+ fi
+ done
+ elif [[ $B_SHOW_BATTERY_FORCED == 'true' ]];then
+ print_data=$( create_print_line "$line_starter" "No battery data found in /sys or dmidecode. Is one present?" )
+ print_screen_output "$print_data"
+ fi
+ eval $LOGFE
+}
+
+print_cpu_data()
+{
+ eval $LOGFS
+ local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data='' a_cpu_speeds=''
+ local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' flag_feature='flags'
+ local a_cpu_working='' cpu_model='' cpu_clock='' cpu_null_error='' max_speed=''
+ local cpc_plural='' cpu_count_print='' model_plural='' cpu_data_string=''
+ local cpu_physical_count='' cpu_core_count='' cpu_core_alpha='' cpu_type=''
+ local cpu_2_data='' working_cpu='' temp1='' per_cpu_cores='' current_max_clock_nu=''
+ local line_starter="CPU:" multi_cpu_starter="${C1}clock speeds$SEP3${C2} "
+ local speed_starter='speed'
+
+ ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\""
+ # Array A_CPU_DATA always has one extra element: max clockfreq found.
+ # that's why its count is one more than you'd think from cores/cpus alone
+ # load A_CPU_DATA
+ get_cpu_data
+
+ IFS=","
+ a_cpu_working=(${A_CPU_DATA[0]})
+ current_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 ))
+ a_cpu_speeds=(${A_CPU_DATA[$current_max_clock_nu]})
+ IFS="$ORIGINAL_IFS"
+
+ # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1
+ # as the parameter to output to the screen, then passing "<text1> ${ARR[@]} <text2>"
+ # will output only <text1> and first element of ARR. That "@" splits in elements and "*" _doesn't_,
+ # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note.
+ # This has been confirmed by #bash on freenode.
+ # The above mentioned only emerges when using the debugging markers below
+ ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------"
+ # unless all these are null, process whatever you have
+ if [[ -n ${a_cpu_working[0]} || -n ${a_cpu_working[1]} || -n ${a_cpu_working[2]} || -n ${a_cpu_working[3]} ]];then
+ cpu_model="${a_cpu_working[0]}"
+ ## assemble data for output
+ cpu_clock="${a_cpu_working[1]}"
+ cpu_vendor=${a_cpu_working[5]}
+ # set A_CPU_CORE_DATA
+ get_cpu_core_count
+ cpu_physical_count=${A_CPU_CORE_DATA[0]}
+ cpu_core_count=${A_CPU_CORE_DATA[3]}
+ cpu_core_alpha=${A_CPU_CORE_DATA[1]}
+ cpu_type=${A_CPU_CORE_DATA[2]}
+
+ if [[ $cpu_physical_count -gt 1 ]];then
+ cpc_plural='(s)'
+ cpu_count_print="$cpu_physical_count "
+ model_plural='s'
+ fi
+ line_starter="CPU$cpc_plural:"
+ if [[ -z $BSD_TYPE ]];then
+ cpu_data_string="$cpu_count_print$cpu_core_alpha core"
+ cpu_data="${C1}$cpu_data_string${C2} ${a_cpu_working[0]}$model_plural ($cpu_type)"
+ else
+ if [[ $cpu_physical_count -gt 1 ]];then
+ per_cpu_cores=$(($cpu_core_count/$cpu_physical_count))
+ cpu_data_string="${C1}Cores$SEP3${C2} $cpu_core_count ($cpu_physical_count $per_cpu_cores core cpus) "
+ else
+ cpu_data_string="${C1}Cores$SEP3${C2} $cpu_core_count "
+ fi
+ if [[ -n $cpu_type ]];then
+ cpu_type=" ($cpu_type)"
+ fi
+ cpu_data="$cpu_data_string${C1}model$SEP3${C2} ${a_cpu_working[0]}$cpu_type"
+ fi
+ if [[ $B_SHOW_CPU == 'true' ]];then
+ # update for multicore, bogomips x core count.
+ if [[ $B_EXTRA_DATA == 'true' ]];then
+ # if [[ $cpu_vendor != 'intel' ]];then
+ # ARM may use the faked 1 cpucorecount to make this work
+ # echo $cpu_core_count $cpu_physical_count
+ if [[ -n ${a_cpu_working[4]} ]];then
+ # new arm shows bad bogomip value, so don't use it
+ if [[ ${a_cpu_working[4]%.*} -gt 50 ]];then
+ bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
+ fi
+ bmip_data=${bmip_data%.*}
+ fi
+ # else
+ # bmip_data="${a_cpu_working[4]}"
+ # fi
+ # bogomips are a linux thing, but my guess is over time bsds will use them somewhere anyway
+ if [[ -n $BSD_TYPE && -z $bmip_data ]];then
+ bmip_data=''
+ else
+ bmip_data="${C1}bmips$SEP3${C2} $bmip_data "
+ fi
+ fi
+ ## note: this handles how intel reports L2, total instead of per core like AMD does
+ # note that we need to multiply by number of actual cpus here to get true cache size
+ if [[ -n ${a_cpu_working[2]} ]];then
+ if [[ -z $BSD_TYPE ]];then
+ if [[ $cpu_vendor != 'intel' ]];then
+ cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))" )
+ else
+ cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count" )
+ fi
+ else
+ cpu_cache=${a_cpu_working[2]}
+ fi
+ else
+ cpu_cache='N/A'
+ fi
+ # only print shortened list
+ if [[ $B_CPU_FLAGS_FULL != 'true' ]];then
+ # gawk has already sorted this output, no flags returns -
+ if [[ $B_EXTRA_DATA == 'true' ]];then
+ cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" "${a_cpu_working[6]}" )
+ cpu_flags="($cpu_flags)"
+ if [[ ${a_cpu_working[6]} == 'true' ]];then
+ flag_feature='features'
+ fi
+ cpu_flags="${C1}$flag_feature$SEP3${C2} $cpu_flags "
+ fi
+ fi
+ # arm cpus do not have flags or cache
+ if [[ ${a_cpu_working[6]} != 'true' ]];then
+ cpu_data="$cpu_data${C2} ${C1}cache$SEP3${C2} $cpu_cache"
+ cpu_2_data="$cpu_flags$bmip_data"
+ else
+ cpu_data="$cpu_data${C2} (ARM)$bmip_data"
+ fi
+ fi
+ # we don't this printing out extra line unless > 1 cpu core
+ if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
+ cpu_clock_speed='' # null < verbosity level 5
+ else
+ if [[ -z ${a_cpu_working[1]} ]];then
+ if [[ -z ${cpu_data/*ARM*/} ]];then
+ temp1=' (ARM)'
+ fi
+ a_cpu_working[1]="N/A$temp1"
+ else
+ a_cpu_working[1]="${a_cpu_working[1]%.*} MHz"
+ fi
+ # this handles bsd case unless we get a way to get max/min cpu speeds
+ if [[ ${a_cpu_speeds[0]} != 'N/A' && ${a_cpu_speeds[2]} != 0 ]];then
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' && ${#A_CPU_DATA[@]} -eq 2 &&
+ $B_SHOW_CPU == 'true' && ${a_cpu_speeds[1]} != 0 ]];then
+ a_cpu_working[1]="${a_cpu_speeds[0]}/${a_cpu_speeds[1]}/${a_cpu_speeds[2]} MHz"
+ speed_starter='speed/min/max'
+ else
+ if [[ ${a_cpu_speeds[0]} == ${a_cpu_speeds[2]} ]];then
+ a_cpu_working[1]="${a_cpu_speeds[0]} MHz (max)"
+ else
+ a_cpu_working[1]="${a_cpu_speeds[0]}/${a_cpu_speeds[2]} MHz"
+ speed_starter='speed/max'
+ fi
+ fi
+ fi
+ cpu_clock_speed="${C1}$speed_starter$SEP3${C2} ${a_cpu_working[1]}"
+ fi
+ cpu_2_data="$cpu_2_data$cpu_clock_speed"
+ else
+ if [[ $BSD_TYPE == 'bsd' && $B_ROOT != 'true' ]];then
+ cpu_null_error=' No permissions for sysctl use?'
+ fi
+ cpu_data="${C2}No CPU data available.$cpu_null_error"
+ fi
+# echo $cpu_data $cpu_2_data
+# echo ln: $( calculate_line_length "$cpu_data $cpu_2_data" )
+# echo cpl: $( create_print_line "$line_starter" "$cpu_2_data" ):
+# echo icols: $COLS_INNER
+# echo tc: $TERM_COLUMNS
+ # echo :${cpu_2_data}:
+ if [[ -n $cpu_2_data && $( calculate_line_length "$cpu_data $cpu_2_data" ) -gt $COLS_INNER ]];then
+ cpu_data=$( create_print_line "$line_starter" "$cpu_data" )
+ line_starter=' '
+ print_screen_output "$cpu_data"
+ cpu_data=$( create_print_line " " "$cpu_2_data" )
+ print_screen_output "$cpu_data"
+ else
+ cpu_data=$( create_print_line "$line_starter" "$cpu_data" )
+ print_screen_output "$cpu_data $cpu_2_data"
+ fi
+ # we don't do this printing out extra line unless > 1 cpu core
+ # note the numbering, the last array item is the min/max/not found for cpu speeds
+ if [[ ${#A_CPU_DATA[@]} -gt 2 && $B_SHOW_CPU == 'true' ]];then
+ if [[ ${a_cpu_speeds[2]} != 0 ]];then
+ if [[ $B_EXTRA_EXTRA_DATA == 'true' && ${a_cpu_speeds[1]} != 0 ]];then
+ max_speed="${C1}min/max$SEP3${C2} ${a_cpu_speeds[1]}/${a_cpu_speeds[2]} MHz "
+ else
+ max_speed="${C1}max$SEP3${C2} ${a_cpu_speeds[2]} MHz "
+ fi
+ fi
+ for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ ))
+ do
+ IFS=","
+ a_cpu_working=(${A_CPU_DATA[i]})
+ IFS="$ORIGINAL_IFS"
+ # note: the first iteration will create a first space, for color code separation below
+ # someone actually appeared with a 16 core system, so going to stop the cpu core throttle
+ # if this had some other purpose which we can't remember we'll add it back in
+ #if [[ $i -gt 10 ]];then
+ # break
+ #fi
+ # echo $(calculate_line_length "$multi_cpu_starter$SEP3 $cpu_multi_clock_data" )
+ working_cpu="$max_speed${C1}$(( i + 1 ))$SEP3${C2} ${a_cpu_working[1]%.*} MHz "
+ max_speed=''
+ if [[ -n $cpu_multi_clock_data && \
+ $( calculate_line_length "$multi_cpu_starter$cpu_multi_clock_data$working_cpu" ) -gt $COLS_INNER ]];then
+ cpu_multi_clock_data=$( create_print_line " " "$multi_cpu_starter$cpu_multi_clock_data" )
+ print_screen_output "$cpu_multi_clock_data"
+ multi_cpu_starter=''
+ cpu_multi_clock_data="$working_cpu"
+ else
+ cpu_multi_clock_data="$cpu_multi_clock_data$working_cpu"
+ fi
+ done
+ fi
+ # print the last line if it exists after loop
+ if [[ -n $cpu_multi_clock_data ]];then
+ cpu_multi_clock_data=$( create_print_line " " "$multi_cpu_starter$cpu_multi_clock_data" )
+ print_screen_output "$cpu_multi_clock_data"
+ fi
+ if [[ $B_CPU_FLAGS_FULL == 'true' ]];then
+ print_cpu_flags_full "${a_cpu_working[3]}" "${a_cpu_working[6]}"
+ fi
+ eval $LOGFE
+}
+
+# takes list of all flags, split them and prints x per line
+# args: $1 - cpu flag string; $2 - arm true/false
+print_cpu_flags_full()
+{
+ eval $LOGFS
+ # note: sort only sorts lines, not words in a string, so convert to lines
+ local cpu_flags_full="$( echo $1 | tr " " "\n" | sort )"
+ local a_cpu_flags='' line_starter='' temp_string=''
+ local i=0 counter=0 starter_length=0 flag='' flag_data=''
+ local line_length='' flag_feature='Flags' spacer='' flag_string=''
+
+ if [[ $2 == 'true' ]];then
+ flag_feature='Features'
+ fi
+ line_starter="CPU $flag_feature$SEP3"
+ starter_length=$(( ${#line_starter} + 1 ))
+ line_starter="${C1}$line_starter${C2} "
+ line_length=$(( $COLS_INNER - $starter_length ))
+ # build the flag line array
+ for flag in $cpu_flags_full
+ do
+ temp_string="$flag_string$spacer$flag"
+ spacer=' '
+ # handle inner line starter
+ if [[ $counter -gt 0 ]];then
+ line_length=$COLS_INNER
+ fi
+ if [[ $line_length -ge ${#temp_string} ]];then
+ flag_string=$temp_string
+ else
+ a_cpu_flags[$counter]=$flag_string
+ flag_string=$flag
+ (( counter++ ))
+ fi
+ temp_string=''
+ done
+ if [[ -n $flag_string ]];then
+ a_cpu_flags[$counter]=$flag_string
+ else
+ a_cpu_flags[$counter]='No CPU flag data found.'
+ fi
+ # then print it out
+ for (( i=0; i < ${#a_cpu_flags[@]};i++ ))
+ do
+ if [[ $i -gt 0 ]];then
+ line_starter=''
+ fi
+ flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" )
+ print_screen_output "$flag_data"
+ done
+ eval $LOGFE
+}