350 lines
11 KiB
Bash
350 lines
11 KiB
Bash
#!/usr/bin/env bash
|
|
# ------------------------------------------------------------------------------
|
|
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
|
# Protected by the BSD3 license. Please read bellow for details.
|
|
#
|
|
# * Redistribution and use in source and binary forms,
|
|
# * with or without modification, are permitted provided
|
|
# * that the following conditions are met:
|
|
# *
|
|
# * Redistributions of source code must retain the above
|
|
# * copyright notice, this list of conditions and the
|
|
# * following disclaimer.
|
|
# *
|
|
# * Redistributions in binary form must reproduce the above
|
|
# * copyright notice, this list of conditions and the following
|
|
# * disclaimer in the documentation and/or other materials
|
|
# * provided with the distribution.
|
|
# *
|
|
# * Neither the name of the copyright holder nor the names
|
|
# * of any other contributors may be used to endorse or
|
|
# * promote products derived from this software without
|
|
# * specific prior written permission.
|
|
# *
|
|
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
# * OF SUCH DAMAGE.
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Show profile version
|
|
# Usage: ver
|
|
ver()
|
|
{
|
|
local PARSED
|
|
|
|
PARSED=$(getopt -o h --long help -n 'ver' -- "$@")
|
|
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
|
if [[ $? -ne 0 ]]; then
|
|
disp E "Invalid options, use \"ver --help\" to display usage."
|
|
return 1
|
|
fi
|
|
|
|
eval set -- "$PARSED"
|
|
while true; do
|
|
case "$1" in
|
|
-h|--help)
|
|
printf "ver: Display the current profile version.\nUsage: ver\n"
|
|
return 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
disp E "Invalid options, use \"ver --help\" to display usage."
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ -z $PROFVERSION ]] && \
|
|
disp W "No version defined. Profile is probably badly installed." && \
|
|
return 1
|
|
disp "Profile version $PROFVERSION."
|
|
}
|
|
export -f ver
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Display weather for the given city (or the default one)
|
|
# Usage: meteo [city1 city2 ...]
|
|
meteo()
|
|
{
|
|
local PARSED
|
|
|
|
PARSED=$(getopt -o h --long help -n 'meteo' -- "$@")
|
|
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
|
if [[ $? -ne 0 ]]; then
|
|
disp E "Invalid options, use \"meteo --help\" to display usage."
|
|
return 1
|
|
fi
|
|
eval set -- "$PARSED"
|
|
while true; do
|
|
case "$1" in
|
|
-h|--help)
|
|
printf "meteo: Fetch weather data.\n"
|
|
printf "Usage: meteo [city1 city2 ...]\n"
|
|
printf "If no city is provided, the default city from configuration will be used.\n"
|
|
return 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
disp E "Invalid options, use \"meteo --help\" to display usage."
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
local cities=("$@")
|
|
local city="" encoded=""
|
|
[[ $# -eq 0 ]] && cities=("${METEO_DEFAULT_CITY:-}")
|
|
|
|
if [[ ${#cities[@]} -eq 0 || -z "${cities[0]}" ]]; then
|
|
disp E "No city given and METEO_DEFAULT_CITY is not set. Use 'meteo <city>'."
|
|
return 1
|
|
fi
|
|
|
|
for city in "${cities[@]}"; do
|
|
encoded=$(urlencode "$city")
|
|
dwl "https://wttr.in/$encoded" || \
|
|
disp E "Failed to fetch weather data for $city."
|
|
done
|
|
}
|
|
export -f meteo
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Display a system information block using only /proc and /sys — no external tools.
|
|
# Usage: pinfo
|
|
pinfo()
|
|
{
|
|
local _row
|
|
_row() {
|
|
printf " %b%-12s%b %b%s%b\n" "$_lbl" "$1" "$_rst" "$_val" "$2" "$_rst"
|
|
}
|
|
|
|
local PARSED
|
|
PARSED=$(getopt -o h --long help -n 'pinfo' -- "$@")
|
|
# shellcheck disable=SC2181
|
|
if [[ $? -ne 0 ]]; then
|
|
disp E "Invalid options, use \"pinfo --help\" to display usage."
|
|
return 1
|
|
fi
|
|
eval set -- "$PARSED"
|
|
while true; do
|
|
case "$1" in
|
|
-h|--help)
|
|
printf "pinfo: Display system information from /proc and /sys (no external tools required).\n"
|
|
printf "Usage: pinfo\n"
|
|
return 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
disp E "Invalid options, use \"pinfo --help\" to display usage."
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# --- Hostname ---
|
|
local hostname_str
|
|
if [[ -r /proc/sys/kernel/hostname ]]; then
|
|
read -r hostname_str < /proc/sys/kernel/hostname
|
|
else
|
|
hostname_str="${HOSTNAME:-unknown}"
|
|
fi
|
|
|
|
# --- OS release (parsed line by line, never sourced) ---
|
|
local os_name="Unknown" os_version=""
|
|
if [[ -r /etc/os-release ]]; then
|
|
local _osr_key _osr_val
|
|
while IFS='=' read -r _osr_key _osr_val; do
|
|
_osr_val="${_osr_val//\"/}"
|
|
case "$_osr_key" in
|
|
NAME) os_name="$_osr_val" ;;
|
|
VERSION_ID) os_version="$_osr_val" ;;
|
|
esac
|
|
done < /etc/os-release
|
|
fi
|
|
|
|
# --- Kernel release ---
|
|
local kernel_str="unknown"
|
|
[[ -r /proc/sys/kernel/osrelease ]] && read -r kernel_str < /proc/sys/kernel/osrelease
|
|
|
|
# --- Architecture (set by bash at startup from the ELF interpreter) ---
|
|
local arch_str="${HOSTTYPE:-unknown}"
|
|
|
|
# --- Uptime (seconds from /proc/uptime) ---
|
|
local uptime_str="unknown"
|
|
if [[ -r /proc/uptime ]]; then
|
|
local _upraw
|
|
read -r _upraw _ < /proc/uptime
|
|
local _upsec="${_upraw%%.*}"
|
|
local _days=$(( _upsec / 86400 ))
|
|
local _hours=$(( (_upsec % 86400) / 3600 ))
|
|
local _mins=$(( (_upsec % 3600) / 60 ))
|
|
local _secs=$(( _upsec % 60 ))
|
|
uptime_str=""
|
|
(( _days > 0 )) && uptime_str+="${_days}d "
|
|
(( _hours > 0 || _days > 0 )) && uptime_str+="${_hours}h "
|
|
uptime_str+="${_mins}m ${_secs}s"
|
|
fi
|
|
|
|
# --- Load average ---
|
|
local load_str="unknown"
|
|
if [[ -r /proc/loadavg ]]; then
|
|
local _l1 _l5 _l15
|
|
read -r _l1 _l5 _l15 _ < /proc/loadavg
|
|
load_str="${_l1} ${_l5} ${_l15} (1/5/15 min)"
|
|
fi
|
|
|
|
# --- CPU model and logical/physical core count (pure bash) ---
|
|
local cpu_model="unknown" cpu_threads=0
|
|
local -A _seen_cores=()
|
|
local _cur_phys="" _cpu_line
|
|
if [[ -r /proc/cpuinfo ]]; then
|
|
while IFS= read -r _cpu_line; do
|
|
case "$_cpu_line" in
|
|
"model name"*|"Model name"*|"Hardware"*)
|
|
[[ "$cpu_model" == "unknown" ]] && cpu_model="${_cpu_line#*: }"
|
|
;;
|
|
"processor"*)
|
|
(( cpu_threads++ ))
|
|
;;
|
|
"physical id"*)
|
|
_cur_phys="${_cpu_line#*: }"
|
|
;;
|
|
"core id"*)
|
|
_seen_cores["${_cur_phys}:${_cpu_line#*: }"]=1
|
|
;;
|
|
esac
|
|
done < /proc/cpuinfo
|
|
fi
|
|
local cpu_cores="${#_seen_cores[@]}"
|
|
(( cpu_cores == 0 )) && cpu_cores=$cpu_threads
|
|
|
|
# --- Memory (pure bash, /proc/meminfo, values in kB) ---
|
|
local mem_total=0 mem_available=0
|
|
if [[ -r /proc/meminfo ]]; then
|
|
local _mkey _mval _munit
|
|
while read -r _mkey _mval _munit; do
|
|
case "${_mkey%:}" in
|
|
MemTotal) mem_total="$_mval" ;;
|
|
MemAvailable) mem_available="$_mval" ;;
|
|
esac
|
|
done < /proc/meminfo
|
|
fi
|
|
local mem_total_mib=$(( mem_total / 1024 ))
|
|
local mem_used_mib=$(( (mem_total - mem_available) / 1024 ))
|
|
|
|
# --- Process count (glob over numeric /proc entries) ---
|
|
local proc_count=0 _pdir
|
|
for _pdir in /proc/[0-9]*/; do
|
|
[[ -d "$_pdir" ]] && (( proc_count++ ))
|
|
done
|
|
|
|
# --- Shell and terminal ---
|
|
local shell_str="${BASH:-bash} ${BASH_VERSION%\(*}"
|
|
local term_str="${TERM:-unknown}"
|
|
|
|
# --- Render ---
|
|
local _lbl="${BIWhite:-}" _val="${ICyan:-}" _rst="${DEFAULTCOL:-}"
|
|
|
|
printf "\n"
|
|
_row "Hostname" "$hostname_str"
|
|
_row "OS" "${os_name}${os_version:+ $os_version}"
|
|
_row "Kernel" "$kernel_str"
|
|
_row "Arch" "$arch_str"
|
|
_row "Uptime" "$uptime_str"
|
|
_row "Load avg" "$load_str"
|
|
_row "CPU" "$cpu_model"
|
|
_row "Cores" "${cpu_cores} physical, ${cpu_threads} logical"
|
|
_row "Memory" "${mem_used_mib} MiB used / ${mem_total_mib} MiB total"
|
|
_row "Processes" "$proc_count"
|
|
_row "Shell" "$shell_str"
|
|
_row "Terminal" "$term_str"
|
|
printf "\n"
|
|
}
|
|
export -f pinfo
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Display system general information
|
|
# Usage: showinfo
|
|
showinfo()
|
|
{
|
|
local PARSED
|
|
|
|
PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@")
|
|
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
|
if [[ $? -ne 0 ]]; then
|
|
disp E "Invalid options, use \"showinfo --help\" to display usage."
|
|
return 1
|
|
fi
|
|
eval set -- "$PARSED"
|
|
|
|
while true; do
|
|
case "$1" in
|
|
-h|--help)
|
|
printf "showinfo: Display system information (hostname, kernel, uptime and fetch output when available).\n"
|
|
printf "Usage: showinfo\n"
|
|
return 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
disp E "Invalid options, use \"showinfo --help\" to display usage."
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
local hostname_str
|
|
local figopt=()
|
|
hostname_str="$(hostname)"
|
|
|
|
printf "\n"
|
|
if command -v figlet >/dev/null 2>&1; then
|
|
[[ -s /usr/share/figlet/ansi_shadow.flf ]] && \
|
|
figopt=(-f ansi_shadow)
|
|
figlet -k "${figopt[@]}" "$hostname_str"
|
|
else
|
|
printf "%s\n" "$hostname_str"
|
|
fi
|
|
|
|
printf "\n"
|
|
if command -v neofetch >/dev/null 2>&1; then
|
|
neofetch
|
|
elif command -v fastfetch >/dev/null 2>&1; then
|
|
fastfetch
|
|
else
|
|
pinfo "$@"
|
|
fi
|
|
}
|
|
export -f showinfo
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
load_conf info
|
|
# EOF
|