//go:build !windows package main import ( "bufio" "fmt" "os" "os/exec" "strings" ) // promptPassword reads a password from stdin with echo disabled via stty. If // stty is unavailable (no tty, missing binary), it falls back to an echoed // read so the command still works in pipes/CI. func promptPassword(label string) (string, error) { fmt.Fprint(os.Stderr, label) echoDisabled := stty("-echo") == nil if echoDisabled { defer func() { _ = stty("echo") fmt.Fprintln(os.Stderr) // the Enter keystroke was not echoed }() } line, err := bufio.NewReader(os.Stdin).ReadString('\n') if err != nil && line == "" { return "", fmt.Errorf("read password: %w", err) } return strings.TrimRight(line, "\r\n"), nil } func stty(arg string) error { cmd := exec.Command("stty", arg) cmd.Stdin = os.Stdin return cmd.Run() }