#!/bin/bash

export LC_ALL=C
d=$(basename "$0")
pgrep "$d -u" >/dev/null && exit 0

# cd /usr/bin && for a in ruptime runame rhw rsw rnet rbench rdisk rload rac rboot rwho; do ln -sf ruptime $a; done

if [ -f /etc/ruptime/ruptime.conf ]; then
    . /etc/ruptime/ruptime.conf
else
    defaults read ch.aiei.ruptime 2>/dev/null >/dev/null
    if [ ! $? = 0 ]; then
        echo "NO CONFIG FOUND in /etc/ruptime/ruptime.conf nor defaults"; exit 1
    else
        #echo "FOUND defaults";
	SERVER=$(defaults read ch.aiei.ruptime SERVER)
	PORT=$(defaults read ch.aiei.ruptime PORT)
	HOSTNAMECMD=$(defaults read ch.aiei.ruptime HOSTNAMECMD)
    fi
fi

if [ -f /etc/ruptime/ruptime.key ]; then
    export KEY=$(cat /etc/ruptime/ruptime.key)
else
    defaults read ch.aiei.ruptime 2>/dev/null >/dev/null
    if [ ! $? = 0 ]; then
        echo "NO KEY FOUND in /etc/ruptime/ruptime.key"; exit 1
    else
        #echo "FOUND defaults";
	export KEY=$(defaults read ch.aiei.ruptime KEY)
    fi
fi

if [ "${SERVER}x" = "x" ]; then echo "SERVER not set"; exit 1; fi
if [ "${PORT}x" = "x" ]; then echo "PORT not set"; exit 1; fi
if [ "${HOSTNAMECMD}x" = "x" ]; then echo "HOSTNAMECMD not set"; exit 1; fi

d=$(basename "$0")
if [ "${1}x" = "-cx" ]; then
    # colors for % output of rload
    exec 1> >(sed "s, [0-9]\.[0-9][0-9],\x1b[38;5;118m&\x1b[0m,g" | sed "s, [0-8][0-9]\.[0-9][0-9],\x1b[38;5;118m&\x1b[0m,g" | sed "s, [9][0-4]\.[0-9][0-9],\x1b[38;5;226m&\x1b[0m,g" | sed "s, [9][5-9]\.[0-9][0-9],\x1b[38;5;208m&\x1b[0m,g" | sed "s, [1-9][0-9][0-9]\.[0-9][0-9],\x1b[38;5;196m&\x1b[0m,g")
fi

if [ "${1}x" = "-vx" ]; then
    cat << INFO
$0 version 1.6
INFO
    exit 0
fi

# initialize all host information
if [ "${1}x" = "-ix" ]; then
    all=$(grep ln $(which ruptime) |sed "s,.*in\ ,,;s,;.*,,"|head -1)
    for a in $all; do
        echo Initializing $a
        $a -u
    done
    exit 0
fi

# show all values of the host
if [ "${1}x" = "-ax" ]; then
    all=$(grep ln $(which ruptime) |sed "s,.*in\ ,,;s,;.*,,"|head -1)
    k=$(eval "$HOSTNAMECMD")
    for a in $all; do
        #echo Initializing $a
        $a | grep $k
    done
    exit 0
fi
if [ "${1}x" = "-ux" ]; then
    k=$(eval "$HOSTNAMECMD")
    case "$d" in
	runame)
	    case "$(uname -s)" in
		Linux|GNU/kFreeBSD)
		    s=$(echo $(lsb_release -a 2>/dev/null | grep -v ^LSB | grep -v ^Desc | awk '{print $NF}'))
		;;
		Darwin)
		    s=$(echo $(sw_vers 2>/dev/null | awk -v OFS="" '{$1=""}{print}'))
		;;
	    esac
	    u=$(printf "%-28s %s, %s\n" "$k" "`uname -srm`" "$s" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	ruptime)
	    u=$(uptime|sed 's/ days\{0,1\},[[:blank:]]\{1,\}/+/; s/ averages\{0,1\}://; s/ min//;s/,//g'|awk -v h=$(eval "$HOSTNAMECMD") '{$1="";printf "%-28s %s %11s %2s %5s %s %6s %6s %6s\n", h, $2, $3, $4, $5, $6, $7, $8, $9}' | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rsw)
rsw=$(for a in dpkg rpm nix snap spack flatpak pip2 pip3 brew zypper; do
    num=""
    which $a &>/dev/null && if [ $a == "dpkg" ]; then num=$(dpkg -l |grep ^ii |wc -l); fi
    which $a &>/dev/null && if [ $a == "rpm" ]; then num=$(rpm -qa | wc -l); fi
    which $a &>/dev/null && if [ $a == "brew" ]; then num=$(brew list| wc -l); fi
    which $a &>/dev/null && if [ $a == "pip2" ]; then num=$(pip2 list 2>/dev/null | wc -l); fi
    which $a &>/dev/null && if [ $a == "pip3" ]; then num=$(pip3 list --local 2>/dev/null |sed "1,2d" |wc -l); fi
    which $a &>/dev/null && if [ $a == "spack" ]; then num=$(spack find 2>/dev/null |wc -l); fi
    which $a &>/dev/null && if [ $a == "snap" ]; then num=$(snap list |sed 1d |wc -l); fi
    which $a &>/dev/null && if [ $a == "flatpak" ]; then num=$(flatpak list | wc -l); fi
    which $a &>/dev/null && if [ $a == "zypper" ]; then num=$(zypper search --installed-only | grep package$ | wc -l); fi
    if [ ${num}x != x ]; then echo -ne "$a $(echo $num) "; fi
done)
	    u=$(printf "%-28s %s\n" "$k" "$rsw" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rhw)
	    biosdate=$(dmidecode -s bios-release-date 2>/dev/null | sed 's,/, ,g'|awk '{print $3"/"$1"/"$2}')
            if [ -f /sys/firmware/devicetree/base/compatible ]; then biosdate=$(echo $(cat /sys/firmware/devicetree/base/compatible|tr -d '\0') | sed "s,.*bcm2835.*,2012/03/01,; s,.*bcm2835.*,2014/07/14,; s,.*bcm2836.*,2015/02/02,; s,.*bcm2837.*,2015/02/02,; s,.*bcm2711.*,2019/06/24,; s,.*rp2040.*,2021/11/02,; s,.*bcm2712.*,2023/10/23,; s,.*j314s.*t6000.*,2021/06/06,; s,.*j316s.*t6000.*,2021/06/06,; s,.*j314c.*t6001.*,2021/06/06,; s,.*j316c.*t6001.*,2021/06/06,; s,.*j375c.*t6001.*,2022/06/06,; s,.*j375d.*t6002.*,2022/06/06,; s,.*j414s.*t6020.*,2023/06/06,; s,.*j416s.*t6020.*,2023/06/06,; s,.*j474s.*t6020.*,2023/06/06,; s,.*j414c.*t6021.*,2023/06/06,; s,.*j416c.*t6021.*,2023/06/06,; s,.*j475c.*t6021.*,2023/06/06,; s,.*j180d.*t6022.*,2023/06/06,; s,.*j475d.*t6022.*,2023/06/06,; s,.*j274.*t8103.*,2020/06/06,; s,.*j293.*t8103.*,2020/06/06,; s,.*j313.*t8103.*,2020/06/06,; s,.*j456.*t8103.*,2021/06/06,; s,.*j457.*t8103.*,2021/06/06,; s,.*j413.*t8112.*,2022/06/06,; s,.*j415.*t8112.*,2023/06/06,; s,.*j473.*t8112.*,2023/06/06,; s,.*j493.*t8112.*,2022/06/06,;"); fi
            # if macOS see https://raw.githubusercontent.com/quacktacular/mac-device-id-to-model/main/models.txt
            if [ -d /sys/firmware/efi/ ]; then sys=UEFI; else sys=BIOS; fi
            # if macOS + arm64 then it's sys=AAPL
            uname -o |grep ^Darwin >/dev/null && uname -m |grep ^arm64 >/dev/null && sys=AAPL
            cat /sys/firmware/devicetree/base/compatible &>/dev/null | grep raspberry && sys=RASP
            #/usr/sbin/lsmod|grep "^nvram " >/dev/null && head -1 /proc/driver/nvram |grep not >/dev/null; if [ "$?" -eq 0 ]; then cmos="CMOS+"; else cmos="CMOS-"; fi
            which free >/dev/null && mem=$(free -b |grep ^Mem: |awk '{printf "%.0f\n", $2/1024/1024/1024}')
            which free >/dev/null || mem=$(sysctl -n hw.memsize|awk '{printf "%.0f\n", $1/1024/1024/1024}')
            cores=$(getconf _NPROCESSORS_ONLN)
            gpu=0; which nvidia-smi >/dev/null && gpu=$(nvidia-smi --query-gpu=utilization.gpu,utilization.memory --format=csv|sed 1d|wc -l)
	    # macOS number-of-GPU-cores system_profiler SPDisplaysDataType |grep "Cores"
            u=$(printf "%-28s %s\n" "$k" "$biosdate $sys $cores $mem $gpu" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
            # macOS system_profiler SPHardwareDataType
	;;
	rac)
	    ac=$(ac | awk '{print $2}')
	    nu=$(ac -p |sed 1d |wc -l)
	    u=$(printf "%-28s %s %s\n" "$k" "$ac" "$nu" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rwho)
	    w=$(who |sed "s/ [a-zA-Z:]/ $(eval "$HOSTNAMECMD"):&/1;s,: ,:,1")
	    u=$(printf "%s\n" "$w" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rbench)
	    dt=date
            which gdate >/dev/null && dt=$(which gdate)
            which free >/dev/null && m=$(free -b |grep ^Mem: |awk '{printf "%.0f\n", $2/1024/1024/1024}')
            which free >/dev/null || m=$(sysctl -n hw.memsize|awk '{printf "%.0f\n", $1/1024/1024/1024}')
            start=$($dt +%s.%N)
            memtester 16M 1 &>/dev/null
            end=$($dt +%s.%N)
            mem=$(printf "MEM %.2f %s GB" $(echo $end - $start | bc) $m)
            arch=$(uname -m)
            cores=$(getconf _NPROCESSORS_ONLN)
            start2=$($dt +%s.%N)
            /bin/echo "scale=3000;4*a(1)" | bc -l &>/dev/null
            end2=$($dt +%s.%N)
            cpu=$(printf "CPU %.2f %s\n" $(echo $end2 - $start2 | bc) $cores)
            u=$(printf "%-28s %s\n" "$k" "$mem $cpu" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rboot)
            r=0
            # logged in users
            liun=$(who |grep -v root | awk '{print $1}' |sort -u|wc -l)
            r=$((r + liun))
            # screen or tmux sessions
            sotn=$(ps -ef |grep 'screen\|tmux' |grep -v grep | awk '{print $1 " " $NF}' |sort -u|wc -l)
            r=$((r + sotn))
            # something is running
            cpu=$(uptime | sed s,.*:,,g | sed s/,//g|awk '{printf("%.0f\n",$(NF-2))}')
            r=$((r + cpu))
            u=$(printf "%-28s %s\n" "$k" "users $liun screen/tmux $sotn CPU $cpu gore $r" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	rnet)
            netdev=$(ip r |grep ^default |head -1|sed "s,.*dev ,,g" |awk '{print $1}')
            s=$(echo "$netdev   $(cat /sys/class/net/${netdev}/speed)Mb/s")
            iwconfig $(echo $s|awk '{print $1}') &>/dev/null; r=$?
            if [ "$r" = 0 ]; then
                l=$(iwconfig $s 2>/dev/null|grep "Link Quality=" | sed "s,Link Quality=,," | awk '{print $1"*100"}' | bc -l);\
                s2=$(iwconfig $s 2>/dev/null|grep "Bit Rate" | sed "s,Bit Rate=,,;s, Mb,Mb,"|awk '{print $1}'); \
                u=$(printf "%-28s %s %s %.0f\n" "$k" "$s" "$s2" "$l" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
            else
                netdev=$(ip r |grep ^default |head -1|sed "s,.*dev ,,g" |awk '{print $1}')
                s=$(echo "$netdev   $(cat /sys/class/net/${netdev}/speed)Mb/s")
                u=$(printf "%-28s %s\n" "$k" "$s" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
            fi
	    # macOS
            # scutil --nwi |tail -1|awk '{print $NF}'
            # /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I
	;;
	rdisk)
	    s=$(echo $(for a in $(ls /dev/ada? /dev/sd? /dev/xvd? /dev/vd? /dev/nvme?n1 /dev/mmcblk? /dev/md[0-9]* 2>/dev/null | sed s,/dev/,,); do echo $a $(fdisk -l /dev/$a 2>/dev/null |grep ^Disk | awk '{printf "%1.0f\n", $5/1000/1000/1000}' | head -1); done))
            u=$(printf "%-28s %s\n" "$k" "$s" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
            # macOS: diskutil info /dev/disk0 |grep Size
	;;
	rload)
	    s=$(uptime | sed "s/,//g" | awk -v c=$(getconf _NPROCESSORS_ONLN) '{printf "%6.2f\n", $(NF-2)*100/c}')
	    case "$(uname -s)" in
		Linux)
                    gpu=$(which nvidia-smi >/dev/null && printf "%6.2f %6.2f\n" $(timeout 29 nvidia-smi --query-gpu=utilization.gpu,utilization.memory --format=csv |sed 1d|sed "s/%//g;s/MiB//g;s/,//g;s/  / /g"|awk '{for(i=1;i<=NF;i++)s[i]+=$i}END{for(i=1;i<=NF;i++)printf("%.2f \n",s[i]/NR)}'))
		    m=$(printf "%6.2f\n" $(free -m -t |tail -1 |awk '{print 100*$3/$2}'))
		;;
		Darwin)
		    total=$(sysctl hw.memsize | awk '{print $NF}')
		    used=$(top -l 1 | grep PhysMem: |sed "s/M//g"|awk '{print $2*1024*1024}')
		    m=$(printf "%6.2f\n" $(echo Mem: $total $used |awk '{print 100*$3/$2}'))
		;;
	    esac
	    u=$(printf "%-28s %s %s %s %s\n" "$k" "$s" "$m" "$gpu" | openssl enc -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out -)
	;;
	*)
	    echo "PROTOCOL ERROR"
	    exit 1
	;;
    esac
    echo "$d $u" | nc "$SERVER" "$PORT"
    exit 0
fi

d=$(basename "$0")
(echo xz."$d") |
(nc "$SERVER" "$PORT") |
(openssl enc -d -A -a -aes-192-cbc -pbkdf2 -pass env:KEY -in - -out - | xz -d 2>/dev/null || echo "NO DATA FOUND ($?)" 1>&2)
