#!/bin/sh
# Displays basic information about the system
# shellcheck disable=SC2048,SC2086
. /etc/os-release

bopt="-c"
opt="-br"
all=""
plain=""

h1()
{
    STR="$*"
    if [ -n "$plain" ]; then
	echo "$STR" | tr '[:lower:]' '[:upper:]'
    else
	printf "\033[7m%-${COLUMNS}s\033[0m\n" "$STR"
    fi
}

h2()
{
    STR="$*"
    if [ -n "$plain" ]; then
	echo "$STR"
	echo "$STR" | sed 's/./-/g'
    else
	printf "\033[1m%-${COLUMNS}s\033[0m\n" "$STR"
    fi
}

dm()
{
    if [ -n "$plain" ]; then
	echo "${*}"
    else
	printf "\033[2m%s\033[0m\n" "$*"
    fi
}

ul()
{
    if [ -n "$plain" ]; then
	printf "__%s__" "$*"
    else
	printf "\033[4%s\033[0m" "$*"
    fi
}

em()
{
    if [ -n "$plain" ]; then
	printf "**%s**" "$*"
    else
	printf "\033[5m%s\033[0m" "$*"
    fi
}

usage()
{
    cat <<EOF
usage:
  show [opt] cmd

options:
  -a            Show all, of something
  -f            Show full output, not brief port/iface listings
  -h            Show this help text
  -n            Show output without any footer
  -p            Show plain output, no bells or whistles

commands:
  dhcp          Show DHCP server
  port PORT     Show port configuration and link information
  ports         Show ports available for bridging
  vlans         Show port groups in bridge
  ifaces        Show interfaces and their addresses
  fdb           Show forwarding database (unicast)
  mdb           Show multicast forwarding database
  stp           Show spanning tree status
  ip   addr     Show IPv4 addresses
       route    Show routing table
  ipv6 addr     Show IPv6 addresses
       route    Show routing table
  log [FILE]    Show latest entries from syslog, or other FILE
  rmon PORT     Show RMON counters for PORT (when applicable)
  system        Show OS details
  version       Show OS verson
EOF
}

is_dhcp_running()
{
    copy operational -x /infix-dhcp-server:dhcp-server | jq -r '
        ."infix-dhcp-server:dhcp-server".enabled as $global |
        if ."infix-dhcp-server:dhcp-server".subnet? then
                (."infix-dhcp-server:dhcp-server".subnet[] |
                select(.enabled != false)) |
                if $global != false and . then "true" else "false" end
        else "false" end
    ' 2>/dev/null | grep -q true
}

dhcp()
{
    if ! is_dhcp_running; then
	echo "DHCP server not enabled."
	exit 0
    fi

    case $1 in
	detail)
	    copy operational -x /infix-dhcp-server:dhcp-server | \
		jq -C .
	    ;;
	stat*)
	    copy operational -x /infix-dhcp-server:dhcp-server | \
		/usr/libexec/statd/cli-pretty "show-dhcp-server" -s
	    ;;
	*)
	    copy operational -x /infix-dhcp-server:dhcp-server | \
		/usr/libexec/statd/cli-pretty "show-dhcp-server"
	    ;;
    esac
}

# Usage 1: show port eth0
# Usage 2: show port
# Usage 3: show ports
#
# The first show ethtool output for 'eth0' (in this case).  The latter
# two are the same, showing a summary of all interfaces classified as
# access ports.
ports()
{
    if [ $# -gt 0 ] && [ -e "/sys/class/net/$1" ]; then
	for port in $*; do
	    ethtool "$port"
	done
	return
    fi

    h1 "PORT             STATE          MAC ADDRESS        FLAGS"
    if grep -q port /etc/iproute2/group; then
	ip $opt link show group port
    else
	ip $opt link show
    fi

    if [ -z "$plain" ] && [ -z "$nofoot" ]; then
	dm "______________________________________________________________________________"
	dm "Use: '[ip|bridge] --help' and '[ip|bridge] link help' for more details."
    fi
}

vlans()
{
    h1 "INTERFACE         VLAN  FLAGS"
    bridge $bopt vlan show |tail +2 | awk 'NF { iface=$1; vid=$2; printf("%-16s  %4d  ", iface, vid); for (i=3; i <= NF; i++) printf("%s ", $i); printf("\n"); }'
    if [ -z "$plain" ] && [ -z "$nofoot" ]; then
	dm "______________________________________________________________________________"
	dm "See: 'bridge --help' and 'bridge vlan help' for more details."
    fi
}

ifaces()
{
    if [ -n "$all" ]; then
	if [ $# -gt 0 ]; then
	    for iface in $*; do
		ip $opt addr show dev "$iface"
	    done
	    return
	fi

	h1 "INTERFACE        STATE          ADDRESS"
	ip $opt addr show
	if [ -z "$plain" ] && [ -z "$nofoot" ]; then
	    dm "______________________________________________________________________________"
	    dm "See: 'ip --help' and 'ip address help' for more details."
	fi
    else
	if [ $# -gt 0 ]; then
	    for iface in $*; do
		copy operational -x \
			   "/ietf-interfaces:interfaces/interface[name='$iface']" | \
		    /usr/libexec/statd/cli-pretty "show-interfaces" -n "$iface"
	    done
	    return
	fi
        copy operational -x /ietf-interfaces:interfaces | \
          /usr/libexec/statd/cli-pretty "show-interfaces"
    fi
}

log()
{
    if [ -n "$1" ] && [ -r "/var/log/$1" ]; then
	fn="/var/log/$1"
    else
	fn="/var/log/syslog"
    fi
    less +G $fn
}

rmon()
{
    if [ -z "$*" ]; then
	echo "Missing argument, see 'show port' for available interfaces"
	exit 1
    fi
    for port in $*; do
	ethtool -S "$port"
    done
    if [ -z "$plain" ] && [ -z "$nofoot" ]; then
	dm "______________________________________________________________________________"
	dm "See: 'ethtool --help' for more details."
    fi
}

rstp()
{
    mstpctl showbridge
    echo "br0 port info"
    mstpctl showport br0
}

stp()
{
    copy operational -x /ietf-interfaces:interfaces | \
        /usr/libexec/statd/cli-pretty "show-bridge-stp"
}

fdb()
{
    bridge $bopt fdb show
}

mdb()
{
    bridge $bopt mdb show
}

routes()
{
    if [ -n "$1" ]; then
	arg="-i $1"
    else
	arg="-i ipv4"
    fi
    copy operational -x /ietf-routing:routing/ribs | \
	/usr/libexec/statd/cli-pretty "show-routing-table" $arg
}

igmp()
{
    mctl $@
}

system()
{
    h1 "SYSTEM INFORMATION"
    echo "System Name        : $(uname -n)"
    echo "System Variant     : $VARIANT"
    echo "System Description : $PRETTY_NAME"
    echo "System Contact     : $HOME_URL"
    echo "System Timezone    : $(cat /etc/timezone)"
    echo "System Type        : $NAME"
    echo "System Version     : $(cat /etc/version)"
    echo "System Arch        : $(uname -m)"
    echo "Kernel Version     : $(uname -sr)"
}

version()
{
    cat /etc/version
}

while [ "$1" != "" ]; do
    case $1 in
	-a)
	    all=1
	    ;;
	-f)
	    opt=""
	    if [ -n "$plain" ]; then
		opt="-color=never"
		bopt="-color=never"
	    fi
	    opt="-d $opt"
	    bopt="-d $bopt"
	    ;;
	-n)
	    nofoot="yes"
	    ;;
	-p)
	    plain="yes"
	    opt="$opt -color=never"
	    bopt="$bopt -color=never"
	    ;;
	-h)
	    usage
	    exit 0
	    ;;
	*)
	    break
    esac
    shift
done

if [ -z "$plain" ]; then
    TTY=$(resize)
    eval "$TTY"

    # COLUMS and ROWS should be set on the console, if not, use fallback
    if [ -z "$COLUMNS" ]; then
	if command -v tput; then
	    COLUMNS=$(tput cols)
	else
	    COLUMNS=80
	fi
    fi
fi

cmd=$1
if [ -n "$cmd" ]; then
    shift
fi

case $cmd in
    help)
	usage
	;;
    dhcp | dhcp-server)
	dhcp $*
	;;
    port*)
	ports $*
	;;
    vlan*)
	vlans
	;;
    fdb)
	fdb
	;;
    mdb)
	mdb
	;;
    ifa*)
	ifaces $*
	;;
    ip)
	cmd=$1
	shift
	case $cmd in
	    addr*)
		all=1
		opt="$opt -d"
		ifaces $*
		;;
	    route*)
		routes ipv4
		;;
	    igmp*)
		igmp $*
		;;
	    *)
		usage
		;;
	esac
	;;
    ipv6)
	cmd=$1
	shift
	case $cmd in
	    addr*)
		ifaces
		;;
	    route*)
		routes ipv6
		;;
	    mld*)
		igmp $*
		;;
	    *)
		usage
		;;
	esac
	;;
    log)
	log $1
	;;
    rmon)
	rmon $*
	;;
    route*)
	routes
	;;
    span*)
	rstp
	;;
    stp*)
	stp
	;;
    sys*)
	system
	;;
    ver*)
	version
	;;
    *)
	usage
	exit 1
	;;
esac
