Skip to content

Commit

Permalink
Merge pull request #96 from loophole/fix/input_from_pipe
Browse files Browse the repository at this point in the history
Fix input from pipe
  • Loading branch information
Morishiri committed Feb 8, 2021
2 parents ff1d551 + c4f82b8 commit 34a87ed
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
31 changes: 25 additions & 6 deletions cmd/virtual-serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
package cmd

import (
"bufio"
"fmt"
"io"
"os"
"strings"

"github.com/beevik/guid"
"github.com/blang/semver/v4"
Expand All @@ -13,6 +16,7 @@ import (
"github.com/loophole/cli/internal/pkg/apiclient"
"github.com/loophole/cli/internal/pkg/cache"
"github.com/loophole/cli/internal/pkg/communication"
"github.com/loophole/cli/internal/pkg/inpututil"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/crypto/ssh/terminal"
Expand Down Expand Up @@ -56,14 +60,29 @@ func parseBasicAuthFlags(flagset *pflag.FlagSet) error {
})

if usernameProvided && !passwordProvided {
fmt.Print("Enter basic auth password: ")
var password string
if !inpututil.IsUsingPipe() { //only ask for password in terminal if not using pipe
fmt.Print("Enter basic auth password: ")
var err error
passwordBytes, err := terminal.ReadPassword(int(os.Stdin.Fd()))
password = string(passwordBytes)
if err != nil {
return err
}
fmt.Println()
} else {
reader := bufio.NewReader(os.Stdin)
passwordBytes, err := reader.ReadBytes('\n')
//if the reader encounters EOF before \n,
//we assume that everything up until EOF is the intended password and continue
if err != nil && err != io.EOF {
communication.Warn("An error occured while reading the basic auth password from pipe.")
communication.Fatal(err.Error())
}
password = strings.TrimSuffix(string(passwordBytes), "\n")

password, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
return err
}
fmt.Println()
passwordFlag.Value.Set(string(password))
passwordFlag.Value.Set(password)
}
if passwordProvided && !usernameProvided {
return fmt.Errorf("When using basic auth, both %s and %s have to be provided", basicAuthUsernameFlagName, basicAuthPasswordFlagName)
Expand Down
15 changes: 10 additions & 5 deletions internal/pkg/closehandler/closehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"syscall"

"github.com/loophole/cli/internal/pkg/communication"
"github.com/loophole/cli/internal/pkg/inpututil"
"golang.org/x/crypto/ssh/terminal"
)

Expand All @@ -14,14 +15,18 @@ var terminalState *terminal.State = &terminal.State{}

// SetupCloseHandler ensures that CTRL+C inputs are properly processed, restoring the terminal state from not displaying entered characters where necessary
func SetupCloseHandler(feedbackFormURL string) {
var terminalState *terminal.State
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
terminalState, err := terminal.GetState(int(os.Stdin.Fd()))
if err != nil {
communication.Warn("Error saving terminal state")
communication.Warn(err.Error())
}

if !inpututil.IsUsingPipe() { //don't try to get terminal state if using a pipe
var err error
terminalState, err = terminal.GetState(int(os.Stdin.Fd()))
if err != nil {
communication.Warn("Error saving terminal state")
communication.Fatal(err.Error())
}
}
go func() {
<-c
if terminalState != nil {
Expand Down
17 changes: 17 additions & 0 deletions internal/pkg/inpututil/inpututil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package inpututil

import (
"os"

"github.com/loophole/cli/internal/pkg/communication"
)

//IsUsingPipe returns whether a pipe is being used for inputs or not
func IsUsingPipe() bool {
stdinInfo, err := os.Stdin.Stat()
if err != nil {
communication.Warn("Error getting terminal info")
communication.Fatal(err.Error())
}
return (stdinInfo.Mode() & os.ModeCharDevice) == 0
}

0 comments on commit 34a87ed

Please sign in to comment.