TallyNote release / linux-x64 (push) Successful in 6m11s
- manual admin password no longer forces first-login change - --generate still requires password change on first login - add --mark-password-configured to repair legacy flag - echo interactive username/password input in SSH terminal - installer prints absolute admin-init path (sudo secure_path compat) - use python3 pty helper for CI tests (no expect on Linux) release: 1.2.9
67 lines
2.0 KiB
Python
Executable File
67 lines
2.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Minimal cross-platform pty driver for the admin-init CLI tests.
|
|
|
|
Forks a child on a real pseudo-terminal so the CLI sees a TTY and runs its
|
|
raw-mode password prompts. Forwards a prepared input file to the child's stdin
|
|
and copies child output to stdout. Writes the child's exit code to a file so
|
|
the Node test can read it deterministically.
|
|
|
|
Used instead of `expect` (not installed on CI) or BSD `script` (injects a stray
|
|
EOT byte when stdin is a regular file, corrupting the first prompt value).
|
|
"""
|
|
import os
|
|
import pty
|
|
import select
|
|
import sys
|
|
|
|
argv = sys.argv[1:]
|
|
exit_file = os.environ.get("PTY_EXIT_FILE", "")
|
|
stdin_file = os.environ.get("PTY_STDIN_FILE", "")
|
|
|
|
pid, master = pty.fork()
|
|
if pid == 0:
|
|
# Child: replace with the target command. argv[0] is an absolute node path.
|
|
os.execvp(argv[0], argv)
|
|
os._exit(127)
|
|
|
|
in_fd = os.open(stdin_file, os.O_RDONLY) if stdin_file else -1
|
|
open_stdin = in_fd >= 0
|
|
try:
|
|
while True:
|
|
fds = [master]
|
|
if open_stdin:
|
|
fds.append(in_fd)
|
|
try:
|
|
readable, _, _ = select.select(fds, [], [], 30.0)
|
|
except (OSError, ValueError):
|
|
break
|
|
if not readable:
|
|
break
|
|
if master in readable:
|
|
try:
|
|
data = os.read(master, 4096)
|
|
except OSError:
|
|
break
|
|
if not data:
|
|
break
|
|
os.write(1, data)
|
|
if open_stdin and in_fd in readable:
|
|
data = os.read(in_fd, 4096)
|
|
if data:
|
|
os.write(master, data)
|
|
else:
|
|
open_stdin = False
|
|
os.close(in_fd)
|
|
finally:
|
|
try:
|
|
_, status = os.waitpid(pid, 0)
|
|
except ChildProcessError:
|
|
status = 0
|
|
code = os.waitstatus_to_exitcode(status) if hasattr(os, "waitstatus_to_exitcode") else (status >> 8)
|
|
if exit_file:
|
|
try:
|
|
with open(exit_file, "w") as handle:
|
|
handle.write(str(code))
|
|
except OSError:
|
|
pass
|