diff --git a/README.rst b/README.rst index fb0f52959..f2f938830 100644 --- a/README.rst +++ b/README.rst @@ -1068,7 +1068,7 @@ substituted with the temporary file path (whether a FIFO or an actual file). .. code:: sh # operating on the same file as before, but as a file this time - $ sops exec-file out.json 'echo your temporary file: {}; cat {}' + $ sops exec-file out.json -- sh -c "echo your temporary file: {}; cat {}" your temporary file: /tmp/.sops894650499/tmp-file { "database_password": "jf48t9wfw094gf4nhdf023r", @@ -1077,7 +1077,7 @@ substituted with the temporary file path (whether a FIFO or an actual file). } # launch a shell with a variable TMPFILE pointing to the temporary file - $ sops exec-file --no-fifo out.json 'TMPFILE={} sh' + $ sops exec-file --no-fifo out.json -- sh -c 'TMPFILE={} sh' sh-3.2$ echo $TMPFILE /tmp/.sops506055069/tmp-file291138648 sh-3.2$ cat $TMPFILE diff --git a/cmd/sops/main.go b/cmd/sops/main.go index d70b501e7..848ef543f 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -164,12 +164,12 @@ func main() { }, }, keyserviceFlags...), Action: func(c *cli.Context) error { - if c.NArg() != 2 { + if c.NArg() < 2 { return common.NewExitError(fmt.Errorf("error: missing file to decrypt"), codes.ErrorGeneric) } fileName := c.Args()[0] - command := c.Args()[1] + command := c.Args()[1:] inputStore := inputStore(c, fileName) @@ -265,12 +265,12 @@ func main() { }, }, keyserviceFlags...), Action: func(c *cli.Context) error { - if c.NArg() != 2 { + if c.NArg() < 2 { return common.NewExitError(fmt.Errorf("error: missing file to decrypt"), codes.ErrorGeneric) } fileName := c.Args()[0] - command := c.Args()[1] + command := c.Args()[1:] inputStore := inputStore(c, fileName) outputStore := outputStore(c, fileName) diff --git a/cmd/sops/subcommand/exec/exec.go b/cmd/sops/subcommand/exec/exec.go index be74a31a4..62babe184 100644 --- a/cmd/sops/subcommand/exec/exec.go +++ b/cmd/sops/subcommand/exec/exec.go @@ -3,6 +3,7 @@ package exec import ( "bytes" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -23,7 +24,7 @@ func init() { } type ExecOpts struct { - Command string + Command []string Plaintext []byte Background bool Pristine bool @@ -95,8 +96,11 @@ func ExecWithFile(opts ExecOpts) error { } env = append(env, opts.Env...) - placeholdered := strings.Replace(opts.Command, "{}", filename, -1) - cmd := BuildCommand(placeholdered) + args := opts.Command[1:] + for i, arg := range args { + args[i] = strings.Replace(arg, "{}", filename, -1) + } + cmd := exec.Command(opts.Command[0], args...) cmd.Env = env if opts.Background { @@ -134,7 +138,7 @@ func ExecWithEnv(opts ExecOpts) error { env = append(env, opts.Env...) - cmd := BuildCommand(opts.Command) + cmd := exec.Command(opts.Command[0], opts.Command[1:]...) cmd.Env = env if opts.Background { diff --git a/cmd/sops/subcommand/exec/exec_unix.go b/cmd/sops/subcommand/exec/exec_unix.go index cc831e798..f46e50948 100644 --- a/cmd/sops/subcommand/exec/exec_unix.go +++ b/cmd/sops/subcommand/exec/exec_unix.go @@ -4,17 +4,12 @@ package exec import ( "os" - "os/exec" "os/user" "path/filepath" "strconv" "syscall" ) -func BuildCommand(command string) *exec.Cmd { - return exec.Command("/bin/sh", "-c", command) -} - func WritePipe(pipe string, contents []byte) { handle, err := os.OpenFile(pipe, os.O_WRONLY, 0600)