diff --git a/start-automaker.mjs b/start-automaker.mjs index 4be58041..97362312 100644 --- a/start-automaker.mjs +++ b/start-automaker.mjs @@ -16,6 +16,39 @@ const __dirname = dirname(__filename); const isWindows = platform() === 'win32'; const args = process.argv.slice(2); +/** + * Detect the bash variant by checking $OSTYPE + * This is more reliable than path-based detection since bash.exe in PATH + * could be Git Bash, WSL, or something else + * @param {string} bashPath - Path to bash executable + * @returns {'WSL' | 'MSYS' | 'CYGWIN' | 'UNKNOWN'} The detected bash variant + */ +function detectBashVariant(bashPath) { + try { + const result = spawnSync(bashPath, ['-c', 'echo $OSTYPE'], { + stdio: 'pipe', + timeout: 2000, + }); + if (result.status === 0) { + const ostype = result.stdout.toString().trim(); + // WSL reports 'linux-gnu' or similar Linux identifier + if (ostype === 'linux-gnu' || ostype.startsWith('linux')) return 'WSL'; + // MSYS2/Git Bash reports 'msys' or 'mingw*' + if (ostype.startsWith('msys') || ostype.startsWith('mingw')) return 'MSYS'; + // Cygwin reports 'cygwin' + if (ostype.startsWith('cygwin')) return 'CYGWIN'; + } + } catch { + // Fall through to path-based detection + } + // Fallback to path-based detection if $OSTYPE check fails + const lower = bashPath.toLowerCase(); + if (lower.includes('cygwin')) return 'CYGWIN'; + if (lower.includes('system32')) return 'WSL'; + // Default to MSYS (Git Bash) as it's the most common + return 'MSYS'; +} + /** * Convert Windows path to Unix-style for the detected bash variant * @param {string} windowsPath - Windows-style path (e.g., C:\path\to\file) @@ -23,24 +56,32 @@ const args = process.argv.slice(2); * @returns {string} Unix-style path appropriate for the bash variant */ function convertPathForBash(windowsPath, bashCmd) { + // Input validation + if (!windowsPath || typeof windowsPath !== 'string') { + throw new Error('convertPathForBash: invalid windowsPath'); + } + if (!bashCmd || typeof bashCmd !== 'string') { + throw new Error('convertPathForBash: invalid bashCmd'); + } + let unixPath = windowsPath.replace(/\\/g, '/'); if (/^[A-Za-z]:/.test(unixPath)) { const drive = unixPath[0].toLowerCase(); const pathPart = unixPath.slice(2); - // Detect bash type from path - if (bashCmd.toLowerCase().includes('cygwin')) { - // Cygwin expects /cygdrive/c/path format - return `/cygdrive/${drive}${pathPart}`; - } else if ( - bashCmd.toLowerCase().includes('system32') || - bashCmd === 'bash.exe' - ) { - // WSL bash is typically in System32 or just 'bash.exe' in PATH - return `/mnt/${drive}${pathPart}`; - } else { - // MSYS2/Git Bash expects /c/path format - return `/${drive}${pathPart}`; + // Detect bash variant via $OSTYPE (more reliable than path-based) + const variant = detectBashVariant(bashCmd); + switch (variant) { + case 'CYGWIN': + // Cygwin expects /cygdrive/c/path format + return `/cygdrive/${drive}${pathPart}`; + case 'WSL': + // WSL expects /mnt/c/path format + return `/mnt/${drive}${pathPart}`; + case 'MSYS': + default: + // MSYS2/Git Bash expects /c/path format + return `/${drive}${pathPart}`; } } return unixPath; diff --git a/start-automaker.sh b/start-automaker.sh index 94f143ab..62adb4a4 100755 --- a/start-automaker.sh +++ b/start-automaker.sh @@ -37,6 +37,32 @@ DEFAULT_SERVER_PORT=3008 WEB_PORT=$DEFAULT_WEB_PORT SERVER_PORT=$DEFAULT_SERVER_PORT +# Port validation function +# Returns 0 if valid, 1 if invalid (with error message printed) +validate_port() { + local port="$1" + local port_name="${2:-port}" + + # Check if port is a number + if ! [[ "$port" =~ ^[0-9]+$ ]]; then + echo "${C_RED}Error:${RESET} $port_name must be a number, got '$port'" + return 1 + fi + + # Check if port is in valid range (1-65535) + if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then + echo "${C_RED}Error:${RESET} $port_name must be between 1-65535, got '$port'" + return 1 + fi + + # Check if port is in privileged range (warning only) + if [ "$port" -lt 1024 ]; then + echo "${C_YELLOW}Warning:${RESET} $port_name $port is in privileged range (requires root/admin)" + fi + + return 0 +} + # Hostname configuration # Use VITE_HOSTNAME if explicitly set, otherwise default to localhost # Note: Don't use $HOSTNAME as it's a bash built-in containing the machine's hostname @@ -510,9 +536,19 @@ check_ports() { ;; [uU]|[uU][sS][eE]) read -r -p "Enter web port (default $DEFAULT_WEB_PORT): " input_web - WEB_PORT=${input_web:-$DEFAULT_WEB_PORT} + input_web=${input_web:-$DEFAULT_WEB_PORT} + if ! validate_port "$input_web" "Web port"; then + continue + fi + WEB_PORT=$input_web + read -r -p "Enter server port (default $DEFAULT_SERVER_PORT): " input_server - SERVER_PORT=${input_server:-$DEFAULT_SERVER_PORT} + input_server=${input_server:-$DEFAULT_SERVER_PORT} + if ! validate_port "$input_server" "Server port"; then + continue + fi + SERVER_PORT=$input_server + echo "${C_GREEN}Using ports: Web=$WEB_PORT, Server=$SERVER_PORT${RESET}" break ;; @@ -802,10 +838,20 @@ resolve_port_conflicts() { local input_pad=$(( (TERM_COLS - 40) / 2 )) printf "%${input_pad}s" "" read -r -p "Enter web port (default $DEFAULT_WEB_PORT): " input_web - WEB_PORT=${input_web:-$DEFAULT_WEB_PORT} + input_web=${input_web:-$DEFAULT_WEB_PORT} + if ! validate_port "$input_web" "Web port"; then + continue + fi + WEB_PORT=$input_web + printf "%${input_pad}s" "" read -r -p "Enter server port (default $DEFAULT_SERVER_PORT): " input_server - SERVER_PORT=${input_server:-$DEFAULT_SERVER_PORT} + input_server=${input_server:-$DEFAULT_SERVER_PORT} + if ! validate_port "$input_server" "Server port"; then + continue + fi + SERVER_PORT=$input_server + center_print "Using ports: Web=$WEB_PORT, Server=$SERVER_PORT" "$C_GREEN" break ;;