#!/bin/bash # CMtec Enhanced Update System - Core Library # Shared functions for logging, UI, health checks, and utilities VERSION="3.0.0" LOG_FILE="/tmp/update_$(date +%Y%m%d_%H%M%S).log" START_TIME=$(date +%s) INTERACTIVE=false # Color definitions and Unicode symbols RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' GRAY='\033[0;37m' BOLD='\033[1m' RESET='\033[0m' # Unicode symbols CHECK="โœ“" CROSS="โœ—" WARNING="โš " INFO="โ„น" ROCKET="๐Ÿš€" GEAR="โš™" TIMER="โฑ" PACKAGE="๐Ÿ“ฆ" # Initialize core variables declare -A ROLES declare -A SYSTEM_INFO # Logging function with colored output log() { local level=$1 shift local message="$*" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "[$timestamp] [$level] $message" >> "$LOG_FILE" case $level in ERROR) echo -e "${RED}${CROSS}${RESET} $message" ;; SUCCESS) echo -e "${GREEN}${CHECK}${RESET} $message" ;; WARNING) echo -e "${YELLOW}${WARNING}${RESET} $message" ;; INFO) echo -e "${BLUE}${INFO}${RESET} $message" ;; SECTION) echo -e "\n${CYAN}${GEAR} $message${RESET}" ;; *) echo -e "${GRAY}$message${RESET}" ;; esac } # Fancy spinner function for long operations spinner() { local pid=$1 local message="$2" local delay=0.08 local spinstr='โ ‹โ ™โ นโ ธโ ผโ ดโ ฆโ งโ ‡โ ' echo -e "${CYAN}${GEAR} $message${RESET}" printf " " while kill -0 $pid 2>/dev/null; do local temp=${spinstr#?} printf "${BLUE}%c${RESET}" "$spinstr" spinstr=$temp${spinstr%"$temp"} sleep $delay printf "\b" done printf "${GREEN}${CHECK}${RESET}\n" } # Progress bar function progress_bar() { local current=$1 local total=$2 local message="$3" local width=40 local percentage=$((current * 100 / total)) local filled=$((current * width / total)) local empty=$((width - filled)) printf "\r${message} ${BLUE}[" printf "%*s" $filled | tr ' ' 'โ–ˆ' printf "%*s" $empty | tr ' ' 'โ–‘' printf "] %d%% (%d/%d)${RESET}" $percentage $current $total if [ $current -eq $total ]; then echo fi } # Timer function show_timer() { local start_time=$1 local end_time=$(date +%s) local elapsed=$((end_time - start_time)) local hours=$((elapsed / 3600)) local minutes=$(((elapsed % 3600) / 60)) local seconds=$((elapsed % 60)) if [ $hours -gt 0 ]; then printf "${CYAN}${TIMER} %02d:%02d:%02d${RESET}" $hours $minutes $seconds else printf "${CYAN}${TIMER} %02dm %02ds${RESET}" $minutes $seconds fi } # Confirmation function for interactive mode confirm() { if [ "$INTERACTIVE" == "true" ]; then local prompt="$1" local default="${2:-n}" echo -ne "${YELLOW}${WARNING} $prompt [y/N]: ${RESET}" read -r response response=${response:-$default} case $response in [yY][eE][sS]|[yY]) return 0 ;; *) return 1 ;; esac else return 0 fi } # System health check function system_health_check() { local section_start=$(date +%s) log SECTION "Running system health check" local issues=0 # Check disk space local root_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//') if [ "$root_usage" -gt 85 ]; then log WARNING "Root filesystem is ${root_usage}% full" ((issues++)) else log SUCCESS "Root filesystem usage: ${root_usage}%" fi # Check available memory local mem_available=$(free -m | awk 'NR==2{printf "%d", $7}') if [ "$mem_available" -lt 512 ]; then log WARNING "Low memory available: ${mem_available}MB" ((issues++)) else log SUCCESS "Available memory: ${mem_available}MB" fi # Check for failed systemd services local failed_services=$(systemctl --failed --quiet --no-legend 2>/dev/null | wc -l) if [ "$failed_services" -gt 0 ]; then log WARNING "$failed_services failed systemd services detected" ((issues++)) else log SUCCESS "All systemd services running normally" fi # Check package manager locks (distro-specific) case "${SYSTEM_INFO[DISTRO]}" in "arch") if [ -f /var/lib/pacman/db.lck ]; then log WARNING "Pacman database is locked" ((issues++)) fi ;; "ubuntu"|"debian") if sudo fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; then log WARNING "APT database is locked" ((issues++)) fi ;; esac if [ $issues -eq 0 ]; then log SUCCESS "System health check passed $(show_timer $section_start)" else log WARNING "System health check found $issues issues $(show_timer $section_start)" if [ "$INTERACTIVE" == "true" ]; then if ! confirm "Continue despite health issues?"; then log INFO "Update cancelled by user due to health issues" exit 1 fi fi fi return $issues } # Error handler function error_handler() { local line_number=$1 local error_code=$2 local command="$3" log ERROR "Script failed at line $line_number with exit code $error_code" log ERROR "Failed command: $command" log ERROR "Check log file: $LOG_FILE" echo -e "\n${RED}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${RESET}" echo -e "${RED}โ•‘${RESET} ${BOLD}SCRIPT FAILED${RESET} ${RED}โ•‘${RESET}" echo -e "${RED}โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ${RESET}" echo -e "${RED}โ•‘${RESET} Line: $line_number ${RED}โ•‘${RESET}" echo -e "${RED}โ•‘${RESET} Exit Code: $error_code ${RED}โ•‘${RESET}" echo -e "${RED}โ•‘${RESET} Log File: $LOG_FILE ${RED}โ•‘${RESET}" echo -e "${RED}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n" exit $error_code } # Fancy header display with original ASCII art show_header() { local hostname=$1 local distro=$2 clear echo -e "\n${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}.${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ \\${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ \\${RESET} ${WHITE} # ${BLUE}| *${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/^. \\${RESET} ${WHITE} a##e #%\" a#\"e 6##% ${BLUE}| | |-^-. | | \\ /${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ .-. \\${RESET} ${WHITE}.oOo# # # # # ${BLUE}| | | | | | X${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ ( ) _\\${RESET} ${WHITE}%OoO# # %#e\" # # ${BLUE}| | | | ^._.| / \\${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ _.~ ~._^\\${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/.^ ^\\ ${GRAY}โ„ข${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${GREEN}${ROCKET} CMtec Universal Update System v$VERSION${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${GRAY}$hostname | $distro | $(date '+%Y-%m-%d %H:%M:%S')${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n" } # Alternative fancy header with original Arch-style ASCII art show_arch_header() { local hostname=$1 clear echo -e "\n${BLUE}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}.${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ \\${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ \\${RESET} ${WHITE} # ${BLUE}| *${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/^. \\${RESET} ${WHITE} a##e #%\" a#\"e 6##% ${BLUE}| | |-^-. | | \\ /${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ .-. \\${RESET} ${WHITE}.oOo# # # # # ${BLUE}| | | | | | X${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ ( ) _\\${RESET} ${WHITE}%OoO# # %#e\" # # ${BLUE}| | | | ^._.| / \\${RESET} ${GRAY}โ„ข${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/ _.~ ~._^\\${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}/.^ ^\\ ${GRAY}โ„ข${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${GREEN}${ROCKET} CMtec '$hostname' Enhanced Update Script${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•‘${RESET} ${GRAY}$(date '+%Y-%m-%d %H:%M:%S')${RESET} ${BLUE}โ•‘${RESET}" echo -e "${BLUE}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n" } # Ubuntu-style header with Ubuntu ASCII art show_ubuntu_header() { local hostname=$1 clear echo -e "\n${YELLOW}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} .--.${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} .-\"''\`(|||)${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} ,\`\\ \\ \`-\`.${RESET} 88 88 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} / \\ \"\`\`-. \`${RESET} 88 88 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} .-. , \`___:${RESET} 88 88 88,888, 88 88 ,88888, 88888 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} (:::) : ___ ${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} \`-\` \` , :${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} \\ / ,..-\` ,${RESET} 88 88 88 88 88 88 88 88 88 ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} \`.\/ / .-.\`${RESET} \"88888\" \"88888\" \"88888\" 88 88 \"8888${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} \`-..-( )${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${RED} \`-\`${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${GREEN}${ROCKET} CMtec Ubuntu Install/Update Script${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•‘${RESET} ${GRAY}$hostname | $(date '+%Y-%m-%d %H:%M:%S')${RESET} ${YELLOW}โ•‘${RESET}" echo -e "${YELLOW}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n" } # Display enabled roles with fancy formatting show_roles() { local role_count=0 for role in "${!ROLES[@]}"; do if [ "${ROLES[$role]}" == "yes" ]; then ((role_count++)) fi done if [ $role_count -eq 0 ]; then log WARNING "No roles enabled" return fi log SECTION "System Configuration" echo -e "${BOLD}${PACKAGE} Enabled Roles ($role_count total):${RESET}" for role in "${!ROLES[@]}"; do if [ "${ROLES[$role]}" == "yes" ]; then case $role in desktop*|DESKTOP*) icon="๐Ÿ–ฅ๏ธ" ;; game*|GAME*) icon="๐ŸŽฎ" ;; music*|MUSIC*) icon="๐ŸŽต" ;; dev*|code*|DEV*|CODE*) icon="๐Ÿ’ป" ;; terminal*|TERMINAL*) icon="๐Ÿ“Ÿ" ;; nvidia*|NVIDIA*) icon="๐ŸŽฏ" ;; vr*|VR*) icon="๐Ÿฅฝ" ;; lab*|LAB*) icon="๐Ÿ”ฌ" ;; bt*|BT*|bluetooth*) icon="๐Ÿ“ถ" ;; hypr*|HYPERLAND*) icon="๐ŸŒŠ" ;; wsl*|WSL*) icon="๐Ÿง" ;; *) icon="โš™๏ธ" ;; esac echo -e " ${CYAN}$icon $role${RESET}" fi done echo } # Final summary with statistics show_final_summary() { local end_time=$(date +%s) local total_time=$((end_time - START_TIME)) local total_hours=$((total_time / 3600)) local total_minutes=$(((total_time % 3600) / 60)) local total_seconds=$((total_time % 60)) # Collect system info for summary local kernel_version=$(uname -r) local role_count=0 for role in "${!ROLES[@]}"; do if [ "${ROLES[$role]}" == "yes" ]; then ((role_count++)) fi done log SECTION "Update Summary" echo -e "\n${GREEN}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—${RESET}" echo -e "${GREEN}โ•‘${RESET} ${BOLD}๐ŸŽ‰ UPDATE COMPLETE! ๐ŸŽ‰${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ${RESET}" echo -e "${GREEN}โ•‘${RESET} ${CYAN}๐Ÿ“Š Statistics:${RESET} ${GREEN}โ•‘${RESET}" if [ $total_hours -gt 0 ]; then echo -e "${GREEN}โ•‘${RESET} โ€ข Total time: ${CYAN}${TIMER} ${total_hours}h ${total_minutes}m ${total_seconds}s${RESET} ${GREEN}โ•‘${RESET}" else echo -e "${GREEN}โ•‘${RESET} โ€ข Total time: ${CYAN}${TIMER} ${total_minutes}m ${total_seconds}s${RESET} ${GREEN}โ•‘${RESET}" fi echo -e "${GREEN}โ•‘${RESET} โ€ข Hostname: ${CYAN}${SYSTEM_INFO[HOSTNAME]}${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} โ€ข Distro: ${CYAN}${SYSTEM_INFO[DISTRO]} ${SYSTEM_INFO[VERSION]}${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} โ€ข Kernel: ${CYAN}$kernel_version${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} โ€ข Active roles: ${CYAN}$role_count enabled${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} โ€ข Log file: ${GRAY}$LOG_FILE${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ${RESET}" echo -e "${GREEN}โ•‘${RESET} ${YELLOW}โš ๏ธ SYSTEM REBOOT RECOMMENDED โš ๏ธ${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•‘${RESET} ${WHITE}Some updates may require a reboot to take effect${RESET} ${GREEN}โ•‘${RESET}" echo -e "${GREEN}โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n" log SUCCESS "Update script completed successfully" log INFO "Total execution time: $(show_timer $START_TIME)" log INFO "System: ${SYSTEM_INFO[DISTRO]} ${SYSTEM_INFO[VERSION]} on ${SYSTEM_INFO[HOSTNAME]}" log INFO "Active roles: $role_count" # Interactive reboot prompt if [ "$INTERACTIVE" == "true" ]; then echo -ne "${YELLOW}${WARNING} Reboot system now? [y/N]: ${RESET}" read -r -t 10 response || response="n" case $response in [yY][eE][sS]|[yY]) log INFO "Rebooting system as requested by user" echo -e "${GREEN}${CHECK} Rebooting in 3 seconds...${RESET}" sleep 1 echo -e "${GREEN}${CHECK} Rebooting in 2 seconds...${RESET}" sleep 1 echo -e "${GREEN}${CHECK} Rebooting in 1 second...${RESET}" sleep 1 sudo reboot ;; *) log INFO "Reboot cancelled by user" echo -e "${BLUE}${INFO} Remember to reboot when convenient!${RESET}" ;; esac else echo -e "${BLUE}${INFO} Please reboot your system when convenient${RESET}" fi echo -e "${GREEN}${CHECK} Thank you for using CMtec Universal Update System!${RESET}\n" } # Utility function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Utility function to check if package is installed (distro-agnostic) package_installed() { local package="$1" case "${SYSTEM_INFO[DISTRO]}" in "arch") pacman -Qs "$package" >/dev/null 2>&1 ;; "ubuntu"|"debian") dpkg -l "$package" >/dev/null 2>&1 ;; *) return 1 ;; esac } # Initialize logging init_core() { # Set error trap trap 'error_handler ${LINENO} $? "$BASH_COMMAND"' ERR # Initialize log log INFO "Starting CMtec Universal Update System v$VERSION" log INFO "Log file: $LOG_FILE" log INFO "Interactive mode: $INTERACTIVE" } # Source guard to prevent double-sourcing if [ -z "$CORE_LIB_LOADED" ]; then CORE_LIB_LOADED=true fi