#!/bin/sh #================================================================# # GitSSH Auto-Installer # Automatically clones and installs GitSSH from GitHub # POSIX Compliant - Fixed for curl | sh usage #================================================================# set -e # Exit on any error # Configuration REPO_URL="https://github.com/gitssh-cli/gitssh" TEMP_DIR="/tmp/gitssh-install-$$" INSTALL_DIR="$TEMP_DIR/gitssh" #================================================================# # UTILITY FUNCTIONS #================================================================# show_banner() { cat << 'EOF' âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â â â âââââââ âââââââââââââââââââ âââ â â ââââââââ âââ âââ âââââââââââââââââââ âââ â â âââ ââââââââââââââââââââââââââââââââââââ â â âââ ââââââ âââ ââââââââââââââââââââââââ â â âââââââââââ âââ âââââââââââââââââââ âââ â â âââââââ âââ âââ âââââââââââââââââââ âââv0.1.0-Oz â â <-POSIX Compliant-> â â â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ Manage Multiple SSH Git and GitHub Account Sessions With Ease! EOF } show_progress() { current="$1" total="$2" message="$3" width=50 # POSIX arithmetic percentage=$((current * 100 / total)) filled=$((current * width / total)) empty=$((width - filled)) printf "\r\033[0;34m[\033[0m" # Print filled portion i=0 while [ $i -lt $filled ]; do printf "â" i=$((i + 1)) done # Print empty portion i=0 while [ $i -lt $empty ]; do printf " " i=$((i + 1)) done printf "\033[0;34m] %d%% - %s\033[0m" "$percentage" "$message" if [ "$current" -eq "$total" ]; then printf "\n" fi } log_info() { printf "\033[0;34m[INFO]\033[0m %s\n" "$1" } log_success() { printf "\033[0;32m[SUCCESS]\033[0m %s\n" "$1" } log_error() { printf "\033[0;31m[ERROR]\033[0m %s\n" "$1" >&2 } log_warning() { printf "\033[1;33m[WARNING]\033[0m %s\n" "$1" } cleanup_on_error() { if [ -d "$TEMP_DIR" ]; then log_info "Cleaning up temporary files due to error..." rm -rf "$TEMP_DIR" fi } cleanup_final() { if [ -d "$TEMP_DIR" ]; then log_info "Cleaning up temporary files..." rm -rf "$TEMP_DIR" fi } check_dependencies() { missing_deps="" # Check for git if ! command -v git >/dev/null 2>&1; then missing_deps="$missing_deps git" fi # Check for chmod if ! command -v chmod >/dev/null 2>&1; then missing_deps="$missing_deps chmod" fi if [ -n "$missing_deps" ]; then log_error "Missing required dependencies:$missing_deps" log_error "Please install them and try again." exit 1 fi } # POSIX Compliant sleep alternative using read with timeout where available posix_sleep() { duration="$1" # Try different sleep methods if command -v sleep >/dev/null 2>&1; then sleep "$duration" elif command -v ping >/dev/null 2>&1; then # Use ping as timer (works on most systems) ping -c 1 -W "${duration}000" 127.0.0.1 >/dev/null 2>&1 || true else # Fallback: busy wait (not ideal but POSIX Compliant) start_time=$(date +%s) while [ $(($(date +%s) - start_time)) -lt "$duration" ]; do continue done fi } # Function to detect if we're running via pipe (curl | sh) is_piped_execution() { # Check if stdin is a pipe [ ! -t 0 ] } # Function to read user input that works with both direct execution and piped execution read_user_input() { printf "\033[1;33mContinue anyway? (y/N): \033[0m" if is_piped_execution; then # When piped, read from terminal directly via /dev/tty if [ -r /dev/tty ]; then read response < /dev/tty else # If /dev/tty is not available, try other methods if command -v tty >/dev/null 2>&1; then tty_device=$(tty) if [ "$tty_device" != "not a tty" ] && [ -r "$tty_device" ]; then read response < "$tty_device" else # Fallback: assume 'y' for automated environments log_warning "No terminal available, proceeding automatically..." response="y" fi else # Final fallback log_warning "No terminal available, proceeding automatically..." response="y" fi fi else # Normal execution - read from stdin read response fi echo "$response" } # Function to wait for user confirmation that works with piped execution wait_for_confirmation() { if is_piped_execution; then # When piped, read from terminal directly printf "\033[1;33mPress Enter to continue with installation...\033[0m" if [ -r /dev/tty ]; then # Read a single line from the terminal head -n 1 < /dev/tty > /dev/null else # If no terminal available, add a short delay and continue log_warning "No terminal available for confirmation, continuing automatically..." posix_sleep 2 fi else # Normal execution printf "\033[1;33mPress Enter to continue with installation...\033[0m" read dummy fi } #================================================================# # MAIN INSTALLATION PROCESS #================================================================# main() { # Set up cleanup trap ONLY for errors and interrupts (not normal exit) trap cleanup_on_error INT TERM # Show banner show_banner # Check dependencies log_info "Checking system dependencies..." check_dependencies show_progress 1 6 "Dependencies checked" posix_sleep 1 # Create temporary directory log_info "Creating temporary directory..." mkdir -p "$TEMP_DIR" show_progress 2 6 "Temporary directory created" posix_sleep 1 # Clone repository log_info "Cloning GitSSH repository..." if git clone "$REPO_URL" "$INSTALL_DIR" >/dev/null 2>&1; then show_progress 3 6 "Repository cloned successfully" else show_progress 3 6 "Repository clone failed" log_error "Failed to clone repository from $REPO_URL" log_error "Please check your internet connection and try again." cleanup_on_error exit 1 fi posix_sleep 1 # Change to install directory log_info "Entering installation directory..." cd "$INSTALL_DIR" show_progress 4 6 "Changed to install directory" posix_sleep 1 # Make install script executable log_info "Making install script executable..." if [ -f "install" ]; then chmod +x install show_progress 5 6 "Install script made executable" else show_progress 5 6 "Install script not found" log_error "Install script not found in repository" log_error "Expected file: $INSTALL_DIR/install" cleanup_on_error exit 1 fi posix_sleep 1 # Complete preparation show_progress 6 6 "Installation preparation complete" printf "\n" # Run installer log_success "Repository downloaded and prepared successfully!" printf "\n" log_info "Starting GitSSH installation..." # Use the new confirmation function that handles piped execution wait_for_confirmation # Clear the trap before running installer (so installer can manage its own cleanup) trap - INT TERM # Execute the install script with proper stdin handling if is_piped_execution; then # When script was piped, we need to ensure the install script can also access terminal if [ -r /dev/tty ]; then # Redirect the install script's stdin to the terminal ./install < /dev/tty else # If no terminal, run without interactive input log_warning "Running installation in non-interactive mode..." ./install fi else # Normal execution ./install fi # Always cleanup after install script finishes, regardless of outcome cleanup_final } #================================================================# # ENTRY POINT #================================================================# # Check if running as root (optional warning) if [ "$(id -u)" -eq 0 ]; then log_warning "Running as root. GitSSH is typically installed for individual users." # Use the new input function that handles piped execution response=$(read_user_input) case "$response" in [yY]|[yY][eE][sS]) log_info "Proceeding with root installation..." ;; *) log_info "Installation cancelled." exit 0 ;; esac fi # Run main installation main "$@"