v0.33.0 tui tap for live view and console enhancements

This commit is contained in:
lixen committed 2026-10-10 21:32:08 -04:00
1 parent a1e9d21d06
commit 87f5576ccf
41 files changed
+4606 -449

No files matched your search

+17
View File
@@ -298,9 +298,26 @@ func readDevice(path, user string, generate bool) ([]byte, bool, error) {
return data, false, err
}
// asker answers in the terminal's place while a host's screen owns it
var asker atomic.Pointer[func(user string, generate bool) ([]byte, error)]
// SetAsker has fn answer what the terminal would be asked; nil asks the
// terminal again. With generate, fn draws a password for an empty answer and
// shows it once, never in a log.
func SetAsker(fn func(user string, generate bool) ([]byte, error)) {
if fn == nil {
asker.Store(nil)
return
}
asker.Store(&fn)
}
// ask prompts on the terminal at path without echo. A generated password is
// shown there only: logs persist, and stderr is often a file.
func ask(path, user string, generate bool) ([]byte, error) {
if fn := asker.Load(); fn != nil {
return (*fn)(user, generate)
}
tty, err := os.OpenFile(path, os.O_RDWR, 0)
if err != nil {
return nil, err
+38
View File
@@ -29,6 +29,7 @@ import (
"github.com/lixenwraith/logwisp/internal/testutil"
"github.com/lixenwraith/auth"
"golang.org/x/term"
)
func TestMain(m *testing.M) {
@@ -689,6 +690,43 @@ func TestOnceReadSourcesAreReadAtStartupOnly(t *testing.T) {
}
}
// While a host's screen owns the terminal its asker answers in the prompt's
// place, once per user, like the terminal (a pty master is a terminal).
func TestAskerAnswersForTheTerminal(t *testing.T) {
probe, err := os.Open("/dev/ptmx")
if err != nil {
t.Skip("no pseudo-terminal:", err)
}
isTerminal := term.IsTerminal(int(probe.Fd()))
probe.Close()
if !isTerminal {
t.Skip("/dev/ptmx is no terminal here")
}
var asked []string
SetAsker(func(user string, generate bool) ([]byte, error) {
asked = append(asked, fmt.Sprintf("%s %v", user, generate))
return []byte("screen-secret"), nil
})
t.Cleanup(func() { SetAsker(nil); readOnce.Lock(); clear(readOnce.m); readOnce.Unlock() })
done := make(chan struct{})
go func() {
defer close(done)
for _, user := range []string{"edge", "edge", "aggregator"} {
if pw, err := ReadPassword("/dev/ptmx", user, true); err != nil || pw != "screen-secret" {
t.Errorf("%s: %q, %v", user, pw, err)
}
}
}()
select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("the terminal was asked, not the asker")
}
if fmt.Sprint(asked) != "[edge true aggregator true]" {
t.Errorf("asked %v", asked)
}
}
// A device is classed by the file it opens, not by stat: FreeBSD stats
// /dev/stdin as a device whatever it holds, so one that is no terminal is read.
func TestADeviceThatIsNoTerminalIsRead(t *testing.T) {