From ea78ff7c644f70422fe6734eba8c946cb49ef8e4 Mon Sep 17 00:00:00 2001 From: Developer Date: Fri, 20 Mar 2026 00:16:12 -0400 Subject: [PATCH] CRITICAL FIX: Add interactive mode detection to prevent tmux crash - Add INTERACTIVE_MODE detection using $- variable - Check if running in interactive shell at startup - Exit gracefully from main menu if non-interactive - Add INTERACTIVE_MODE checks to all submenu handlers - All read operations now properly detect non-interactive environments Root cause: In non-interactive shells (like when sourced via curl | tar xz), /dev/tty doesn't exist. With set -eo pipefail, the read command fails and causes script to crash. Now detects this and exits gracefully with a helpful message. Impact: Fixes tmux crash on AlmaLinux 8 when pulling dev branch via curl. --- launcher.sh | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/launcher.sh b/launcher.sh index 8fcc30d..da77948 100755 --- a/launcher.sh +++ b/launcher.sh @@ -10,6 +10,14 @@ set -eo pipefail +# Check if running in interactive mode +if [[ $- != *i* ]]; then + # Non-interactive mode - set flag for read operations + INTERACTIVE_MODE=0 +else + INTERACTIVE_MODE=1 +fi + # Configuration SUITE_VERSION="2.1.0-BETA" BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -24,6 +32,18 @@ source "$LIB_DIR/domain-discovery.sh" || { echo "ERROR: Failed to load domain-di source "$LIB_DIR/user-manager.sh" || { echo "ERROR: Failed to load user-manager.sh"; return 1; } source "$LIB_DIR/reference-db.sh" || { echo "ERROR: Failed to load reference-db.sh"; return 1; } +# Safe read helper function - handles both interactive and non-interactive modes +safe_read_choice() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + # Non-interactive: return 1 to indicate read failed + return 1 + fi + + if ! read -r choice /dev/null; then + return 1 + fi +} + # Color codes RED='\033[0;31m' YELLOW='\033[1;33m' @@ -198,6 +218,10 @@ show_threat_analysis_menu() { } handle_threat_analysis_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_threat_analysis_menu if ! read -r choice /dev/null; then @@ -234,6 +258,10 @@ show_live_monitoring_menu() { } handle_live_monitoring_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_live_monitoring_menu if ! read -r choice /dev/null; then @@ -268,6 +296,10 @@ show_log_viewers_menu() { } handle_log_viewers_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_log_viewers_menu if ! read -r choice /dev/null; then @@ -301,6 +333,10 @@ show_security_actions_menu() { } handle_security_actions_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_security_actions_menu if ! read -r choice /dev/null; then @@ -337,6 +373,10 @@ show_security_menu() { } handle_security_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_security_menu if ! read -r choice /dev/null; then @@ -387,6 +427,10 @@ show_website_menu() { } handle_website_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_website_menu if ! read -r choice /dev/null; then @@ -442,6 +486,10 @@ show_performance_menu() { } handle_performance_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_performance_menu if ! read -r choice /dev/null; then @@ -463,6 +511,10 @@ handle_performance_menu() { } handle_loadwatch_analyzer() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + show_banner echo -e "📊 Loadwatch Health Analyzer" echo "" @@ -552,6 +604,10 @@ show_acronis_menu() { } handle_backup_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_backup_menu if ! read -r choice /dev/null; then @@ -569,6 +625,10 @@ handle_backup_menu() { } handle_acronis_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_acronis_menu if ! read -r choice /dev/null; then @@ -625,6 +685,10 @@ show_email_menu() { } handle_email_menu() { + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + return 0 # Non-interactive mode, exit + fi + while true; do show_email_menu if ! read -r choice /dev/null; then @@ -727,6 +791,14 @@ main() { while true; do show_main_menu + # Check if interactive mode + if [ "$INTERACTIVE_MODE" -eq 0 ]; then + echo "" + echo "Non-interactive mode: Use this toolkit in an interactive terminal." + echo "Try: source run.sh" + return 0 + fi + # Read from terminal (use /dev/tty directly for interaction) if ! read -r choice /dev/null; then # No terminal available, return from function gracefully