The cursor-report size probe (tty_columns_lines: Save + Goto(999,999) +
\x1B[6n) is unreliable on the fbcond console. console_draw does not clamp Goto
beyond the real screen bounds, so the \x1B[6n reply can report the *current*
cursor position mid boot-text (observed 15x56) instead of the actual
dimensions. A bogus 15-column width makes the login shell wrap every line
oddly.
Keep the probe result only when both dimensions are plausible (cols 40..=1000,
lines 10..=1000); otherwise fall back to the safe 80x30 default, which
mis-wraps on no real framebuffer. A correct full-size reading needs
fbcond/console_draw to answer the probe properly (tracked separately).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The framebuffer login prompt had no visible caret (unlike a Linux VT): boot
output / the \x1Bc reset path can leave DECTCEM off. Emit ESC[?25h (show cursor)
alongside the pre-login clear so the prompt shows a cursor. (If fbcond does not
render a cursor glyph at all, that is a separate fbcond gap.)
The pre-exec child runs chdir(home) before execvp; chdir(/home/user) fails with
ENOENT on the live image (open succeeds, chdir does not) which aborted the whole
spawn before execve - the real reason the login shell never started. Use login's
already-validated cwd (home if reachable, else /). Diagnostics retained.
The username is read with the liner line editor, which puts the console
pty into raw mode (ICANON/ECHO cleared) and does not restore it. In raw
mode the pty line discipline never flushes a completed line into the
slave read buffer the way a shell's canonical read_line expects, so the
interactive shell (brush) never receives a typed command even though
getty forwards it to the pty master. Reset stdin to sane cooked settings
(ICANON|ECHO|ISIG, ICRNL, OPOST|ONLCR, VMIN=1/VTIME=0) via tcsetattr
before spawning the shell.
The login name is read via the liner line editor, which puts the console
fd into non-blocking (and raw) mode and does not restore it. The shell
inherits fd 0; an interactive shell doing blocking line reads on a
non-blocking pty slave never receives forwarded input (reads return
empty), so the shell can never run a command. Clear O_NONBLOCK on
stdin/stdout/stderr in spawn_shell before spawning. Restores the login
namespace restriction (skipping it did not affect the symptom).
Getty forwards console input to the pty master correctly (verified), and
login reads the username fine, but after apply_login_schemes() restricts
the namespace the interactive shell's pty-slave read never returns the
forwarded input. Temporarily skip the restriction to confirm it is the
cause. Also removes the getty forward diagnostic.
The login shell spawn was failing/hanging because login inherits its CWD
from init, which on the live image is on the 'initfs' scheme.
apply_login_schemes() switches to a namespace with only DEFAULT_SCHEMES
(no 'initfs'), leaving that inherited CWD fd unresolvable; relibc resolves
paths through the CWD fd (AT_REDOX_CWD_FD), so the shell child's chdir +
execve then fail with ENOENT (getty respawns login in a loop) or hang.
chdir into the user's home (on the always-present 'file' scheme, fallback
'/') while still in the full namespace, so the CWD fd stays valid after
the restriction and the shell spawns.
The real fix is in init (no longer leaves an initfs-scheme CWD that is
invalid in the restricted login namespace), so spawn_shell can stay
minimal again.
After apply_login_schemes() swaps into the restricted login namespace
(only DEFAULT_SCHEMES), the CWD inherited from init on the live image is
/scheme/initfs, whose scheme is NOT in that namespace. File operations
that consult the CWD fd (notably the child's execve opening the shell
binary) then block, so the login shell never starts. chdir to the user's
home (fallback /), both on the always-present 'file' scheme, before
spawning. Also drops the temporary spawn_shell diagnostics.
Probe the shell binary and home directory in the (possibly restricted)
login namespace before spawning, and print the exact spawn error with
raw_os_error. This isolates whether a failed login shell spawn is due to
a missing binary, an unreachable cwd/home, or an exec-time error.
grantpt() and unlockpt() need to be used according to the standard, even
though our grantpt is a no-op (since we auto-lock ptys as we give them
out).
This is part of my series for ptyd. This can be safely merged as long as
the relibc/ and base/ changes are merged at the same time.
Previously root would need to know its own password. On Linux root can
change its own password without needing to enter its own password. It
can do so on Redox OS already anyway by directly editing /etc/shadow.