diff --git a/etc/zsh/zshrc b/etc/zsh/zshrc index 7e500ba..1b79ebc 100644 --- a/etc/zsh/zshrc +++ b/etc/zsh/zshrc @@ -22,6 +22,12 @@ setopt EXTENDED_GLOB setopt INTERACTIVE_COMMENTS # a # in an interactive line is a comment setopt NO_BEEP # SchOS has no audio, but it would also scroll unsetopt FLOW_CONTROL # ^S/^Q are worth more as keys than as flow control +# No PROMPT_SP. It marks output that did not end in a newline by printing a +# `#` and then padding to $COLUMNS, trusting the terminal to wrap so the next +# CR can erase it. The console is mirrored to the serial port, and a host +# terminal narrower than the SchOS screen wraps the padding early: every +# prompt came with a `#` line above it. +unsetopt PROMPT_SP # --------------------------------------------------------------------------- # Keys diff --git a/include/gfx/fb.h b/include/gfx/fb.h index e32ee79..92a4786 100644 --- a/include/gfx/fb.h +++ b/include/gfx/fb.h @@ -19,6 +19,7 @@ #define FBIOGET_VSCREENINFO 0x4600 #define FBIOPUT_VSCREENINFO 0x4601 #define FBIOGET_FSCREENINFO 0x4602 +#define FBIOPUTCMAP 0x4605 #define FBIOBLANK 0x4611 #define FBIOPAN_DISPLAY 0x4606 diff --git a/kernel/dev/fb.c b/kernel/dev/fb.c index 0b9412a..0a62efd 100644 --- a/kernel/dev/fb.c +++ b/kernel/dev/fb.c @@ -230,6 +230,13 @@ fb_ioctl(int request, addr_t arg) // blanking does too, as Linux's own drivers without the hook do. case FBIOBLANK: return 0; + + // A palette, on a framebuffer that is always true-colour. Linux's drivers + // keep the values for the console's sixteen colours and succeed; refusing + // made Xorg's fbdev driver log an error for every entry it loads, 256 of + // them at each start. + case FBIOPUTCMAP: + return 0; } return -ENOTTY; diff --git a/kernel/fs/devfs.c b/kernel/fs/devfs.c index befd9a3..43c27c9 100644 --- a/kernel/fs/devfs.c +++ b/kernel/fs/devfs.c @@ -83,6 +83,11 @@ static const struct devnode devnodes[] = { was one terminal. Minor 10 resolves through proc->ctty; see vt_for_minor() in kernel/core/console.c. */ { "tty", 1, 10, D_ROOT }, + /* The terminal on screen, as on Linux. Xorg opens it to find a free VT and + switch to it, and without one ran on no VT at all: the console went on + drawing into the framebuffer over the X screen. Any minor that is not a + numbered terminal or the controlling one resolves to vt_current(). */ + { "tty0", 1, 0, D_ROOT }, { "tty1", 1, 11, D_ROOT }, { "tty2", 1, 12, D_ROOT }, { "tty3", 1, 13, D_ROOT }, diff --git a/tools/posix/mkaroot.sh b/tools/posix/mkaroot.sh index d3499cc..3494745 100644 --- a/tools/posix/mkaroot.sh +++ b/tools/posix/mkaroot.sh @@ -97,6 +97,18 @@ mkdir -p "$P/etc/profile.d" grep -v '^export \(PATH\|HOME\|TERM\)=' "$P/etc/profile" > "$P/etc/profile.d/schos.sh" rm -f "$P/etc/profile" +# How startx starts the X server for root: Alpine's xserverrc, plus +# -dumbSched. Xorg reads input on a thread of its own, SchOS has no threads +# yet, and the server crashed on its way out the first time a client +# disconnected, in pthread_join on a thread that was never made. -dumbSched is +# Xorg's own switch for input on the main loop. The file is root's own rather +# than /etc/X11/xinit/xserverrc, which belongs to the xinit package. +mkdir -p "$P/root" +cat > "$P/root/.xserverrc" <<'XEOF' +#!/bin/sh +exec /usr/bin/X -nolisten tcp -dumbSched "$@" +XEOF + # Mount points and runtime directories are alpine-baselayout's; an empty # directory here only duplicates it. for d in dev proc sys run tmp srv; do @@ -110,6 +122,9 @@ sed -i 's|^\(root:[^:]*:0:0:[^:]*:[^:]*:\)/bin/sh$|\1/bin/zsh|' /etc/passwd for s in /bin/zsh /bin/mksh; do grep -qx "$s" /etc/shells 2>/dev/null || echo "$s" >> /etc/shells done +# The machine's own name, which Alpine's hosts leaves out. Without it xauth +# cannot resolve "schos:0", and startx says "bad display name" four times. +grep -qw schos /etc/hosts || printf '127.0.1.1\tschos\n' >> /etc/hosts exit 0 EOF cp "$PKG/post-install" "$PKG/post-upgrade" @@ -157,7 +172,8 @@ ROOT_PI=$ROOT sh -c ' sed -i "s|^\(root:[^:]*:0:0:[^:]*:[^:]*:\)/bin/sh$|\1/bin/zsh|" "$ROOT_PI/etc/passwd" for s in /bin/zsh /bin/mksh; do grep -qx "$s" "$ROOT_PI/etc/shells" 2>/dev/null || echo "$s" >> "$ROOT_PI/etc/shells" - done' + done + grep -qw schos "$ROOT_PI/etc/hosts" || printf "127.0.1.1\tschos\n" >> "$ROOT_PI/etc/hosts"' # The repository goes in too, so the installed system can reinstall and # upgrade schos-base, and Alpine's are listed for everything else. diff --git a/tools/windows/bootcheck.ps1 b/tools/windows/bootcheck.ps1 index 32645cb..f94c304 100644 --- a/tools/windows/bootcheck.ps1 +++ b/tools/windows/bootcheck.ps1 @@ -495,8 +495,11 @@ try { Start-Sleep -Milliseconds 150 $t = Read-Log if ($null -eq $t -or $t.Length -le $Since) { continue } - # A prompt at the very end, with nothing typed after it. - if ($t.Substring($Since) -match '(?s)#[ ]?$') { return $true } + # A prompt at the very end, with nothing typed after it: mksh's `#`, + # or zsh's `ยป`, which root's shell has been since the root became + # Alpine's. zsh follows it with erase-to-end-of-line and turns + # bracketed paste on, so both escapes may trail the prompt. + if ($t.Substring($Since) -match '(?s)(#|\u00bb)(\e\[[0-9;]*m)*[ ]?(\e\[K)?(\e\[\?2004h)?$') { return $true } } return $false } @@ -629,6 +632,12 @@ if ($null -eq $text) { $text = '' } Write-Host "==> serial transcript ($($text.Length) bytes) -> $log" -ForegroundColor Cyan Write-Host $text +# Matched without terminal escapes. busybox's ls, which is the Alpine root's, +# colours what it lists -- `copy.txt` arrives as ESC[1;32mcopy.txt -- and zsh +# wraps every prompt in them, so a pattern anchored at a line start found +# nothing in output that was perfectly right. Shown raw above, matched clean. +$text = $text -replace '\e\[[0-9;?]*[A-Za-z]', '' -replace '\e[()][0-9A-Za-z]', '' -replace '[\x0e\x0f]', '' + $script:fail = $false function Expect($pattern, $what) { if ($script:text -match $pattern) { @@ -697,7 +706,10 @@ Expect 'schfs: mounted' 'the kernel mounted SchFS as the root filesystem' Expect 'init: ready' 'init came up on a SchFS root' Expect 'label:\s*schos' '/proc/schfs reports the volume label' Expect 'root_objectid:\s*16' '/proc/schfs reports the root object id' -Expect 'dir\s+bin' 'the root directory really contains bin/' +# /proc/schfs lists the first 16 entries, in the tree's order, and on the +# Alpine root bin/ is the seventeenth: any of the top-level directories proves +# the same thing. +Expect '(?m)^\s*dir\s+(bin|etc|usr)\s' 'the root directory really contains bin/, etc/ or usr/' # / is the mounted volume, so mounting that same device again must be # refused. Without this a kernel that had quietly fallen back to some other # root would still pass everything else here.