From d0ec8fa5cf044c70fbfb35334cfe29bd83c03b45 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 12 Apr 2023 21:10:13 +0200 Subject: [PATCH] cli/command: ConfigureAuth: fix terminal state not being restored on error ConfigureAuth used the readInput() utility to read the username and password. However, this utility did not return errors it encountered, but instead did an os.Exit(1). A result of this was that the terminal was not restored if an error happened. When reading the password, the terminal is configured to disable echo (i.e. characters are not printed), and failing to restore the previous state means that the terminal is now "non-functional". This patch: - changes readInput() to return errors it encounters - uses a defer() to restore terminal state Signed-off-by: Sebastiaan van Stijn --- cli/command/registry.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/cli/command/registry.go b/cli/command/registry.go index 22c5cff0c2..621a6c7fc5 100644 --- a/cli/command/registry.go +++ b/cli/command/registry.go @@ -113,7 +113,11 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.") } promptWithDefault(cli.Out(), "Username", authconfig.Username) - flUser = readInput(cli.In(), cli.Out()) + var err error + flUser, err = readInput(cli.In()) + if err != nil { + return err + } flUser = strings.TrimSpace(flUser) if flUser == "" { flUser = authconfig.Username @@ -128,12 +132,15 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes return err } fmt.Fprintf(cli.Out(), "Password: ") - term.DisableEcho(cli.In().FD(), oldState) - - flPassword = readInput(cli.In(), cli.Out()) + _ = term.DisableEcho(cli.In().FD(), oldState) + defer func() { + _ = term.RestoreTerminal(cli.In().FD(), oldState) + }() + flPassword, err = readInput(cli.In()) + if err != nil { + return err + } fmt.Fprint(cli.Out(), "\n") - - term.RestoreTerminal(cli.In().FD(), oldState) if flPassword == "" { return errors.Errorf("Error: Password Required") } @@ -145,14 +152,14 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes return nil } -func readInput(in io.Reader, out io.Writer) string { - reader := bufio.NewReader(in) - line, _, err := reader.ReadLine() +// readInput reads, and returns user input from in. It tries to return a +// single line, not including the end-of-line bytes. +func readInput(in io.Reader) (string, error) { + line, _, err := bufio.NewReader(in).ReadLine() if err != nil { - fmt.Fprintln(out, err.Error()) - os.Exit(1) + return "", errors.Wrap(err, "error while reading input") } - return string(line) + return string(line), nil } func promptWithDefault(out io.Writer, prompt string, configDefault string) {