diff --git a/pkg/settings/parser/parser.go b/pkg/settings/parser/parser.go index 38a64814..b9a2b534 100644 --- a/pkg/settings/parser/parser.go +++ b/pkg/settings/parser/parser.go @@ -610,6 +610,16 @@ func (a *Arguments) parseLongOption(arg, param string) (usedNext bool, err error } func (a *Arguments) parseStdin() error { + fi, err := os.Stdin.Stat() + if err != nil { + return err + } + + // Ensure data is piped + if (fi.Mode() & os.ModeCharDevice) != 0 { + return errors.New(gotext.Get("argument '-' specified without input on stdin")) + } + scanner := bufio.NewScanner(os.Stdin) scanner.Split(bufio.ScanLines) diff --git a/pkg/settings/parser/parser_test.go b/pkg/settings/parser/parser_test.go index 013ee9a9..0e4956a6 100644 --- a/pkg/settings/parser/parser_test.go +++ b/pkg/settings/parser/parser_test.go @@ -1,9 +1,11 @@ package parser import ( + "os" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestOption_Add(t *testing.T) { @@ -330,3 +332,39 @@ func Test_isArg(t *testing.T) { got = isArg("dbpath") assert.True(t, got) } + +func TestArguments_ParseStdin(t *testing.T) { + input := []byte("yay") + + r, w, err := os.Pipe() + require.NoError(t, err) + + _, err = w.Write(input) + require.NoError(t, err) + w.Close() + + // Restore stdin after the test. + defer func(o *os.File) { os.Stdin = o }(os.Stdin) + os.Stdin = r + + args := MakeArguments() + err = args.parseStdin() + assert.NoError(t, err) + + expectedTargets := []string{string(input)} + assert.ElementsMatch(t, args.Targets, expectedTargets) +} + +func TestArguments_ParseStdin_broken_pipe(t *testing.T) { + r, _, err := os.Pipe() + require.NoError(t, err) + r.Close() // Close early to break pipe + + // Restore stdin after the test. + defer func(o *os.File) { os.Stdin = o }(os.Stdin) + os.Stdin = r + + args := MakeArguments() + err = args.parseStdin() + assert.Error(t, err) +}