Skip to content

fix: installer crash when piped (curl/irm | python) on Windows and POSIX - #9

Merged
chengggit merged 2 commits into
mainfrom
fix/install-script
Oct 4, 2026
Merged

chengggit merged 2 commits into
mainfrom
fix/install-script

Conversation

@chengggit

Copy link
Copy Markdown
Owner

Problem

Both install commands in the README crash when the script is piped in:

  • Linux/macOS — curl -fsSL ... | python → termios.error: (25, 'Not a tty') while rendering the menu
  • Windows — irm ... | py → EOFError: EOF when reading a line at the Enter install path: prompt

Root cause: piping the script makes stdin the pipe. Python parses the program
from stdin, so by the time the installer runs, stdin is neither a TTY nor readable.
The menu survived on Windows only because get_key() reads the console via
msvcrt; the path prompt used input(), which reads stdin → EOF → traceback.

Changes

  • get_input_stream() — when stdin isn't a TTY (POSIX), read keypresses and
    prompts from /dev/tty instead; falls back to a plain numbered menu when no
    terminal exists at all.
  • read_line() — on Windows, read the custom path from the console with
    msvcrt (same mechanism the menu already uses) instead of input(). Handles
    Enter, Backspace, Ctrl+C, and ignores arrow/function-key byte prefixes.
  • ask_custom_path() — EOF is treated as "no path provided" → the existing
    clean cancel, instead of a traceback.
  • ASCII-only TUI/messages (❯→>, ↑/↓→Up/Down, …→..., —→-) so
    output doesn't depend on UTF-8 console encoding, and survives PowerShell 5.1's
    ASCII $OutputEncoding when piping.

Running `curl -fsSL .../install.py | python` made sys.stdin the pipe
(exhausted after reading the script), so termios.tcgetattr(sys.stdin)
crashed with "Inappropriate ioctl for device".

- read keypresses and the custom path prompt from /dev/tty when stdin
  is not a TTY, matching how sys.stdin normally behaves
- fall back to a plain numbered menu when no terminal exists at all
- open /dev/tty with newline="\n" so the universal-newline decoder's
  pending-CR logic can't swallow the first Enter (needed two presses)
Piping the installer in (irm ... | python) makes stdin the pipe, so input() in ask_custom_path() raised EOFError at the Enter install path prompt. The arrow-key menu kept working because it reads the console via msvcrt instead of stdin; the prompt now does the same via a new read_line(), and EOF is treated as 'no path provided' instead of crashing.

Also switch the TUI and messages to ASCII-only (selected marker, navigation hint, ellipsis, em dash) so rendering does not depend on UTF-8 console encoding.
@chengggit
chengggit merged commit 038b634 into main Oct 4, 2026
1 check passed
@chengggit
chengggit deleted the fix/install-script branch October 4, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant