summaryrefslogtreecommitdiff
path: root/cmd/podman/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/exec.go')
-rw-r--r--cmd/podman/exec.go70
1 files changed, 52 insertions, 18 deletions
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index 4917fb606..a6afbf75a 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -2,23 +2,23 @@ package main
import (
"fmt"
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/spf13/cobra"
+ "io/ioutil"
"os"
+ "strconv"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/cmd/podman/shared/parse"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
+ "github.com/spf13/cobra"
)
var (
execCommand cliconfig.ExecValues
- execDescription = `
- podman exec
-
- Run a command in a running container
+ execDescription = `Execute the specified command inside a running container.
`
_execCommand = &cobra.Command{
Use: "exec [flags] CONTAINER [COMMAND [ARG...]]",
@@ -37,16 +37,18 @@ var (
func init() {
execCommand.Command = _execCommand
+ execCommand.SetHelpTemplate(HelpTemplate())
execCommand.SetUsageTemplate(UsageTemplate())
flags := execCommand.Flags()
flags.SetInterspersed(false)
- flags.StringSliceVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
+ flags.StringArrayVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
flags.BoolVarP(&execCommand.Interfactive, "interactive", "i", false, "Not supported. All exec commands are interactive by default")
flags.BoolVarP(&execCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&execCommand.Privileged, "privileged", false, "Give the process extended Linux capabilities inside the container. The default is false")
flags.BoolVarP(&execCommand.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false")
flags.StringVarP(&execCommand.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command")
+ flags.IntVar(&execCommand.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container")
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -82,22 +84,54 @@ func execCmd(c *cliconfig.ExecValues) error {
return errors.Wrapf(err, "unable to exec into %s", args[0])
}
- pid, err := ctr.PID()
- if err != nil {
- return err
- }
- became, ret, err := rootless.JoinNS(uint(pid))
- if err != nil {
- return err
+ if c.PreserveFDs > 0 {
+ entries, err := ioutil.ReadDir("/proc/self/fd")
+ if err != nil {
+ return errors.Wrapf(err, "unable to read /proc/self/fd")
+ }
+ m := make(map[int]bool)
+ for _, e := range entries {
+ i, err := strconv.Atoi(e.Name())
+ if err != nil {
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name())
+ }
+ }
+ m[i] = true
+ }
+ for i := 3; i < 3+c.PreserveFDs; i++ {
+ if _, found := m[i]; !found {
+ return errors.New("invalid --preserve-fds=N specified. Not enough FDs available")
+ }
+ }
+
}
- if became {
- os.Exit(ret)
+
+ if os.Geteuid() != 0 {
+ var became bool
+ var ret int
+
+ data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
+ if err != nil {
+ return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile)
+ }
+ conmonPid, err := strconv.Atoi(string(data))
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse PID %q", data)
+ }
+ became, ret, err = rootless.JoinDirectUserAndMountNS(uint(conmonPid))
+ if err != nil {
+ return err
+ }
+ if became {
+ os.Exit(ret)
+ }
}
// ENVIRONMENT VARIABLES
env := map[string]string{}
- if err := readKVStrings(env, []string{}, c.Env); err != nil {
+ if err := parse.ReadKVStrings(env, []string{}, c.Env); err != nil {
return errors.Wrapf(err, "unable to process environment variables")
}
envs := []string{}
@@ -113,5 +147,5 @@ func execCmd(c *cliconfig.ExecValues) error {
streams.AttachError = true
streams.AttachInput = true
- return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams)
+ return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
}