#!/bin/sh
##
## Show the UNIX OS information
##
## SPDX-FileCopyrightText: 2006-2024 SATOH Fumiyasu @ OSSTech Corp., Japan
## SPDX-License-Identifier: GPL-2.0-or-later
##

orig_PATH_exist="$(env |grep '^PATH=')"
orig_PATH="$PATH"
orig_LC_ALL_exist="$(env |grep '^LC_ALL=')"
orig_LC_ALL="$LC_ALL"
PATH="/opt/osstech/sbin:/opt/osstech/bin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:$PATH"
if locale -a |grep -E -i '^c.utf-?8$' >/dev/null; then
  LC_ALL=C.UTF-8
else
  LC_ALL=C
fi
export PATH LC_ALL

renice 1 "$$" >/dev/null 2>&1 || :
ionice -c 2 -n 5 -p "$$" >/dev/null 2>&1 || :

uname="$(uname)"

flag_progress=""
cmd_usage="Usage: $0 [OPTIONS]

Options:
-p
  Print running command to standard error
  e.g. \`$0 -p >unixinfo.txt\`
-h
  Print this help message
"

while getopts ph opt; do
  case "$opt" in
  p)
    flag_progress="yes"
    ;;
  h)
    echo "$cmd_usage"
    exit 0
    ;;
  *)
    exit 1
    ;;
  esac
done

echo_title()
{
  echo "==== UNIXINFO: $(date '+%Y-%m-%d %H:%M:%S'): $*"
  if [ -n "$flag_progress" ]; then
    echo "UNIXINFO: $* ..." 1>&2
  fi
}

info_run()
{
  echo_title "$@"
  echo "---- command type: $(type "$1" 2>&1)"
  "$@" 2>&1
  echo
}

info_eval()
{
  echo_title "$1"
  sh -c "$1" 2>&1
  echo
}

info_cat()
{
  for _info_cat in "$@"; do
    echo_title "$_info_cat"
    cat  "$_info_cat" 2>&1
    echo
  done
}

## ======================================================================

echo_title version
sed -n '/^#.*Date: /{s/,.*$//;s/^.* //;p;q;}' "$0"

info_run date '+%Y-%m-%d %a %H:%M:%S %z'
info_run uname -a

echo_title env
env \
  ${orig_PATH_exist:+PATH="$orig_PATH"} \
  ${orig_LC_ALL_exist:+LC_ALL="$orig_LC_ALL"} \
  |sort

info_cat /etc/motd
case "$uname" in
Linux)
  if [ -f /etc/debian_version ]; then
    info_cat /etc/debian_version
  else
    info_cat /etc/*-release
  fi
  info_cat /proc/cpuinfo
  info_run lscpu
  info_run dmidecode
  info_cat /proc/devices /proc/ioports /proc/iomem /proc/interrupts /proc/dma
  info_cat /proc/pci /proc/scsi/scsi
  info_run lspci -vv
  info_run lspci -vvn
  info_run lsusb -vv
  info_run lsmod
  info_cat /etc/modprobe.conf
  info_cat /etc/modules.conf
  if [ -f /etc/debian_version ]; then
    info_cat /etc/modules
    info_cat /etc/modprobe.d/*
  fi
  info_cat /proc/cmdline
  info_cat /etc/modprobe.conf /etc/modules
  ;;
esac

info_run rpm -qa --last
case "$uname" in
Linux)
  if [ -f /etc/debian_version ]; then
    info_run env COLUMNS=200 dpkg -l
  else
    info_run chkconfig --list
  fi
  if type systemctl >/dev/null 2>&1; then
    info_run systemctl status --no-pager --full
    info_run systemctl list-units --no-pager --full --all
    info_run systemctl list-unit-files --no-pager --full
    info_run systemctl list-timers --no-pager --full --all
    info_run systemd-cgls --no-pager --full --all
    info_run journalctl --no-pager --full --catalog --output=short-iso
  fi
  info_cat /etc/ld.so.conf /etc/ld.so.conf.d/*.conf
  ;;
*BSD)
  info_run pkg_info
  info_cat /etc/ld*.so.conf
  info_cat /etc/mail/mailer.conf
  ;;
esac

info_run who -r
info_cat /etc/inittab
info_cat /etc/rc.local
if [ -d /etc/rc0.d ]; then
  info_run ls /etc/rc?.d
elif [ -d /etc/rc.d/rc0.d ]; then
  info_run ls /etc/rc.d/rc?.d
fi

for file in /etc/default/* /etc/sysconfig/* /etc/security/*; do
  [ -f "$file" ] && info_cat "$file"
done

case "$uname" in
Linux)
  info_run sestatus
  if [ -f /etc/debian_version ]; then
    info_cat /etc/locale.gen
    ## Sarge and older
    info_cat /etc/environment
  fi
  info_run sysctl -a
  info_run free
  info_cat /proc/meminfo
  info_cat /proc/slabinfo
  info_run swapon -s
  info_run ipcs -l
  info_run ipcs -u
  info_run pstree -acpu
  ;;
*BSD)
  info_run sysctl -a
  info_cat /etc/auth.conf
  ;;
esac
info_run getconf -a

find /etc/cron* /var/spool/cron -type f -print 2>/dev/null \
  |while read -r cronfile; do
    info_cat "$cronfile"
  done

info_run ipcs -a
if ps a >/dev/null 2>&1; then
  ## BSD-style
  info_run ps auxwwww
  ## Dump environment variables after command-line (e)
  info_run ps auxwwwwe
elif [ -x /usr/ucb/ps ]; then
  ## BSD-style
  info_run /usr/ucb/ps auxwwww
  ## Dump environment variables after command-line (e)
  info_run /usr/ucb/ps auxwwwwe
fi

case "$uname" in
Linux)
  info_run ps -eFl --forest
  ;;
esac

## FIXME: vmstat 1 5
## FIXME: mpstat 1 5

## CPU utilization
info_run sar -u
## Memory and swap utilization
info_run sar -r
## Status of process, i-node, file tables
info_run sar -v
## Queue length
info_run sar -q
## System switching activity (and swapping on Solaris)
info_run sar -w
case "$uname" in
Linux)
  ## System swapping statictics
  info_run sar -W
  ## Paging statistics
  info_run sar -B
  ## Activity for each block devic
  info_run sar -d
  ;;
esac

info_run w
info_run last
case "$uname" in
Linux)
  for l in dmesg warn err crit alert emerg; do
    info_run dmesg --level "$l" --color=always --nopager
  done
  info_cat /var/log/dmesg
  info_cat /var/log/boot*
  info_cat /var/log/messages
  ;;
*)
  info_cat /var/log/messages
  ;;
esac
info_cat /var/log/syslog

info_cat /etc/*fstab
info_run mount
info_run ls -la /boot
info_cat /boot/grub/menu.lst /boot/grub/device.map
case "$uname" in
Linux)
  info_cat /proc/stat /proc/filesystems /proc/partitions /proc/mounts
  info_cat /proc/sys/fs/file-max /proc/sys/fs/file-nr
  info_run lsblk --all -o NAME,TYPE,FSTYPE,SIZE,SCHED,UUID,RO,MOUNTPOINT
  info_run fdisk -l
  info_run df -akl
  info_run df -ail
  ## Software RAID (md)
  info_cat /proc/mdstat
  info_cat /etc/raidtab /etc/mdadm.conf /etc/mdadm/mdadm.conf
  ## LVM
  info_run pvdisplay
  info_run vgdisplay
  info_run lvdisplay
  info_run repquota -auv
  info_run repquota -agv
  ;;
*)
  info_run df -k
  info_run df -i
  ;;
esac
info_cat /etc/auto[_.]*

info_run ifconfig -a
if type ethtool >/dev/null 2>&1; then
  ifconfig -a |sed -n 's/[: ].*//;/^[a-z]/p' \
  |grep -E -v '^(lo[0-9]*|sit[0-9]|vmnet[0-9])$' \
  |while read -r if; do
    info_run ethtool "$if"
  done
fi
info_cat /etc/hosts /etc/resolv.conf /etc/nsswitch.conf /etc/host.conf /etc/nscd.conf
info_cat /etc/protocols /etc/networks /etc/netmasks /etc/services /etc/rpc
info_cat /etc/*ldap*.conf
info_cat /etc/pam.conf /etc/pam.d/*
info_cat /etc/krb5.conf /etc/krb5/krb5.conf
info_cat /etc/hosts.allow /etc/hosts.deny
info_cat /etc/inetd.conf
case "$uname" in
Linux)
  info_cat cat /root/anaconda-ks.cfg
  if [ -f /etc/debian_version ]; then
    info_cat /etc/network/interfaces
  else
    info_cat /etc/sysconfig/network
    info_cat /etc/sysconfig/network-scripts/ifcfg-*
    info_cat /etc/sysconfig/network-scripts/route-*
  fi
  if firewall-cmd --state >/dev/null 2>&1; then
    info_run firewall-cmd --get-active-zones
    info_run firewall-cmd --get-default-zone
    info_run firewall-cmd --list-all --permanent
    info_run firewall-cmd --list-all-zones --permanent
    info_run firewall-cmd --list-ports --permanent
    info_run firewall-cmd --list-sources --permanent
    info_run firewall-cmd --list-rich-rule --permanent
    info_run firewall-cmd --direct --get-all-rules
  else
    ## FIXME: Dump nftables info
    info_run iptables -nvL -t filter
    info_run iptables -nvL -t nat
    info_run iptables -nvL -t mangle
    info_run iptables -nvL -t raw
    info_run iptables -nvL -t security
    info_run ip6tables -nvL -t filter
    info_run ip6tables -nvL -t nat
    info_run ip6tables -nvL -t mangle
    info_run ip6tables -nvL -t raw
    info_run ip6tables -nvL -t security
  fi
  info_run netstat -anp
  info_run ip -s link
  info_run ip -s neighbor
  info_run ip addr
  info_run ip maddr
  info_run ip route
  info_run ip mroute
  info_run ip rule
  info_run ip tunnel
  info_run ss -aeiomp
  info_run nmcli device show
  info_run nmcli connection show
  ;;
*)
  info_run netstat -an
  ;;
esac
info_run netstat -rn
info_run netstat -in
info_run netstat -s
if type lsof >/dev/null 2>&1; then
  info_run lsof -b -n -l -R +c0 +M +E
fi

info_run rpcinfo -p
info_run exportfs

info_run showmount -e
info_run showmount -d
info_run nfsstat

## FIXME
info_eval 'getent passwd |wc -l'
info_eval 'getent group |wc -l'
info_run wc -l /etc/passwd /etc/group

## Mailbox
if [ -d /var/mail ]; then
  mbox_dir="/var/mail"
elif [ -d /var/spool/mail ]; then
  mbox_dir="/var/spool/mail"
fi
if [ -n "${mbox_dir:-}" ]; then
  echo_title "Mailbox usage - size (kBytes)"
  du -sk "$mbox_dir"/* |sort -nr
  echo_title "Mailbox usage - number of messages"
  for mbox in "$mbox_dir"/*;do
    printf '%10d %s\n' "$(grep -c "^From " "$mbox")" "$mbox"
  done \
  |sort -nr \
  ;
fi

echo_title "Maildir usage - size (kBytes)"
getent passwd |cut -d: -f6 \
  |sort -u \
  |while read -r home; do
    [ -d "$home/Maildir" ] && echo "$home/Maildir"
  done \
  |xargs du -sk \
  |sort -nr \
  ;
echo_title "Maildir usage - number of messages"
getent passwd |cut -d: -f6 \
  |sort -u \
  |while read -r home; do
    [ -d "$home/Maildir" ] && echo "$home/Maildir"
  done \
  |while read -r maildir; do
    printf '%10d %s\n' "$(find "$maildir" -type f |wc -l)" "$maildir"
  done \
  |sort -nr \
  ;

## Date, Time, NTP
if type timedatectl >/dev/null 2>&1; then
  info_run timedatectl status
  info_run timedatectl show
  info_run timedatectl timesync-status
  info_run timedatectl show-timesync
fi
if type chronyc >/dev/null 2>&1; then
  info_run chronyc sources
  info_run chronyc -n sources
else
  info_run ntpq -p -n
  info_cat /etc/ntp.conf
  info_cat /etc/ntp/ntpservers
fi

echo_title Done.
