#!/bin/sh # ─< ANSI color codes >─────────────────────────────────────────────────────────────────── RED='\033[0;31m' CYAN='\033[0;36m' YELLOW='\033[0;33m' LIGHT_GREEN='\033[0;92m' BOLD='\033[1m' NC='\033[0m' # ─< Initialize storage variables >─────────────────────────────────────────────────────── _STORED_ERRORS="" _STORED_WARNINGS="" _STORED_INFOS="" _STORED_NOTES="" # ─< echo functions that store and display messages >──────────────────────────── echo_error() { message="${RED}$1${NC}\n" printf "$message" >&2 _STORED_ERRORS="${_STORED_ERRORS}${message}" } echo_warning() { message="${YELLOW}$1${NC}\n" printf "$message" _STORED_WARNINGS="${_STORED_WARNINGS}${message}" } echo_info() { message="${CYAN}$1${NC}\n" printf "$message" _STORED_INFOS="${_STORED_INFOS}${message}" } echo_note() { message="${LIGHT_GREEN}$1${NC}\n" printf "$message" _STORED_NOTES="${_STORED_NOTES}${message}" } # ─< Improved display function that only shows categories with content >────────────────── display_stored_messages() { has_messages=0 # ─< First check if we have any messages at all >───────────────────────────────────────── if [ -z "$_STORED_ERRORS" ] && [ -z "$_STORED_WARNINGS" ] && [ -z "$_STORED_INFOS" ] && [ -z "$_STORED_NOTES" ]; then return 0 fi # ─< Now display each non-empty category with proper spacing >──────────────────────────── if [ -n "$_STORED_ERRORS" ]; then printf "\n${BOLD}${RED}=== Errors ===${NC}\n" printf "$_STORED_ERRORS" has_messages=1 fi if [ -n "$_STORED_WARNINGS" ]; then [ "$has_messages" -eq 1 ] && printf "\n" printf "${BOLD}${YELLOW}=== Warnings ===${NC}\n" printf "$_STORED_WARNINGS" has_messages=1 fi if [ -n "$_STORED_INFOS" ]; then [ "$has_messages" -eq 1 ] && printf "\n" printf "${BOLD}${CYAN}=== Info ===${NC}\n" printf "$_STORED_INFOS" has_messages=1 fi if [ -n "$_STORED_NOTES" ]; then [ "$has_messages" -eq 1 ] && printf "\n" printf "${BOLD}${LIGHT_GREEN}=== Notes ===${NC}\n" printf "$_STORED_NOTES" fi } # ─< Check if the given command exists silently >───────────────────────────────────────── command_exists() { command -v "$@" >/dev/null 2>&1 } # ─< Check if the user is root and set $_sudo variable if necessary >─────────────────────── check_root() { if [ "$(id -u)" -ne 0 ]; then if command_exists sudo; then echo_binfo "User is not root. Using $_sudo for privileged operations." _sudo="sudo" else echo_error "No sudo found and you're not root! Can't install packages." return 1 fi else echo_binfo "Root access confirmed." _sudo="" fi } # ─< Distribution detection and installation >──────────────────────────────────────── get_packager() { if [ -e /etc/os-release ]; then echo_info "Detecting distribution..." . /etc/os-release # ─< Convert $ID and $ID_LIKE to lowercase >────────────────────────────────────────────── ID=$(printf "%s" "$ID" | tr '[:upper:]' '[:lower:]') ID_LIKE=$(printf "%s" "$ID_LIKE" | tr '[:upper:]' '[:lower:]') case "$ID" in ubuntu | pop) install_debian ;; debian) install_debian ;; fedora) install_fedora ;; # alpine) inst_alpine ;; arch | manjaro | garuda | endeavour) install_arch ;; # opensuse*) inst_opensuse ;; *) if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then install_debian elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then install_debian elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then inst_arch elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then install_fedora # elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then # inst_opensuse else echo_error "Unsupported distribution: $ID" exit 1 fi ;; esac else echo_error "Unable to detect distribution. /etc/os-release not found." exit 1 fi } # Function to add user to the 'libvirt' group and start services configure_libvirt() { echo_note "Adding user to 'libvirt' group..." $_sudo usermod -aG libvirt "$(whoami)" echo_note "Starting and enabling libvirt service..." if command -v systemctl &>/dev/null; then $_sudo systemctl start libvirtd $_sudo systemctl enable libvirtd else echo_warning "systemctl command not found, skipping service management." fi echo_note "Configuration complete. You might need to log out and log back in for group changes to take effect." } # Install packages for Debian/Ubuntu/Pop!_OS install_debian() { echo_info "Updating package list..." $_sudo apt update -y echo_info "Installing virt-manager, qemu-full, and related packages..." $_sudo apt install -y virt-manager qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils echo_note "Installation complete on Debian/Ubuntu/Pop!_OS!" } # Install packages for Fedora install_fedora() { echo_info "Updating package list..." $_sudo dnf check-update -y echo_info "Installing virt-manager, qemu-full, and related packages..." $_sudo dnf install -y virt-manager qemu-kvm libvirt libvirt-client bridge-utils echo_note "Installation complete on Fedora!" } # Install packages for Arch Linux/Manjaro/EndeavourOS install_arch() { echo_info "Updating package list..." $_sudo pacman -Syu --noconfirm echo_info "Installing virt-manager, qemu-full, and related packages..." $_sudo pacman -S --noconfirm virt-manager qemu-full libvirt dnsmasq bridge-utils echo_note "Installation complete on Arch Linux/Manjaro/EndeavourOS!" } # Install packages for openSUSE install_opensuse() { echo_info "Updating package list..." $_sudo zypper refresh echo_info "Installing virt-manager, qemu-full, and related packages..." $_sudo zypper install -y virt-manager qemu-kvm libvirt libvirt-client bridge-utils echo_note "Installation complete on openSUSE!" } main() { check_root && get_packager && configure_libvirt display_stored_messages } main