mirror of
https://github.com/xroche/httrack.git
synced 2026-08-13 11:12:19 +03:00
* Tell an stdin at end of file from a keypress select() reporting stdin readable does not mean there is anything to read: at end of file it stays ready forever, and check_stdin() sold that to the crawl loop as an ENTER. The display then toggled on every pass, so a terminal run with stdin closed alternated between the spinner and the full panel. Peek a byte before answering yes, and drop the fflush(stdin) that would have discarded it (undefined on an input stream anyway). The Windows branch reads the console queue rather than stdin, so it has no end of file to confuse. Closes #1072 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * Model the ticket's terminal at EOF, not just a redirection The EOF leg fed httrack /dev/null, so a fix that simply gave up off a terminal would have passed it while leaving the reported bug alive. Add a third crawl that types ^D into the pty, which is the case #1072 describes. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> --------- Signed-off-by: Xavier Roche <roche@httrack.com> Signed-off-by: Xavier Roche <xroche@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
Python
Executable File
48 lines
1.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Run a command with a pty for stdout/stderr and capture what it paints.
|
|
|
|
Usage: ttyrun.py <capture-file> [--stdin tty|eof] [--send enter|eot] -- <cmd> [args...]
|
|
|
|
--stdin tty (default) hands the child the pty, --stdin eof gives it /dev/null.
|
|
--send types one ENTER, or one ^D to put the terminal at end of file, as soon
|
|
as the child paints.
|
|
"""
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import termios
|
|
|
|
capture = sys.argv[1]
|
|
opts = sys.argv[2 : sys.argv.index("--")]
|
|
argv = sys.argv[sys.argv.index("--") + 1 :]
|
|
stdin_mode = opts[opts.index("--stdin") + 1] if "--stdin" in opts else "tty"
|
|
keys = {"enter": b"\n", "eot": b"\004"}
|
|
send = keys[opts[opts.index("--send") + 1]] if "--send" in opts else None
|
|
|
|
master, slave = os.openpty()
|
|
attrs = termios.tcgetattr(slave)
|
|
attrs[1] &= ~termios.ONLCR # or the pty manufactures the CRs a spinner check counts
|
|
termios.tcsetattr(slave, termios.TCSANOW, attrs)
|
|
devnull = os.open(os.devnull, os.O_RDONLY) if stdin_mode == "eof" else None
|
|
p = subprocess.Popen(
|
|
argv, stdin=slave if devnull is None else devnull, stdout=slave, stderr=slave
|
|
)
|
|
os.close(slave)
|
|
if devnull is not None:
|
|
os.close(devnull)
|
|
|
|
with open(capture, "wb") as f:
|
|
while True:
|
|
try:
|
|
data = os.read(master, 4096)
|
|
except OSError: # the slave closed: EIO on Linux, empty read on BSD
|
|
break
|
|
if not data:
|
|
break
|
|
f.write(data)
|
|
if send:
|
|
os.write(master, send)
|
|
send = None
|
|
os.close(master)
|
|
sys.exit(p.wait())
|