github.com/scorpionis/docker@v1.6.0-rc7/daemon/execdriver/native/exec.go (about)

     1  // +build linux
     2  
     3  package native
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  	"syscall"
    10  
    11  	"github.com/docker/docker/daemon/execdriver"
    12  	"github.com/docker/libcontainer"
    13  	_ "github.com/docker/libcontainer/nsenter"
    14  	"github.com/docker/libcontainer/utils"
    15  )
    16  
    17  // TODO(vishh): Add support for running in priviledged mode and running as a different user.
    18  func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
    19  	active := d.activeContainers[c.ID]
    20  	if active == nil {
    21  		return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
    22  	}
    23  
    24  	var term execdriver.Terminal
    25  	var err error
    26  
    27  	p := &libcontainer.Process{
    28  		Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
    29  		Env:  c.ProcessConfig.Env,
    30  		Cwd:  c.WorkingDir,
    31  		User: c.ProcessConfig.User,
    32  	}
    33  
    34  	if processConfig.Tty {
    35  		config := active.Config()
    36  		rootuid, err := config.HostUID()
    37  		if err != nil {
    38  			return -1, err
    39  		}
    40  		cons, err := p.NewConsole(rootuid)
    41  		if err != nil {
    42  			return -1, err
    43  		}
    44  		term, err = NewTtyConsole(cons, pipes, rootuid)
    45  	} else {
    46  		p.Stdout = pipes.Stdout
    47  		p.Stderr = pipes.Stderr
    48  		p.Stdin = pipes.Stdin
    49  		term = &execdriver.StdConsole{}
    50  	}
    51  	if err != nil {
    52  		return -1, err
    53  	}
    54  
    55  	processConfig.Terminal = term
    56  
    57  	if err := active.Start(p); err != nil {
    58  		return -1, err
    59  	}
    60  
    61  	if startCallback != nil {
    62  		pid, err := p.Pid()
    63  		if err != nil {
    64  			p.Signal(os.Kill)
    65  			p.Wait()
    66  			return -1, err
    67  		}
    68  		startCallback(&c.ProcessConfig, pid)
    69  	}
    70  
    71  	ps, err := p.Wait()
    72  	if err != nil {
    73  		exitErr, ok := err.(*exec.ExitError)
    74  		if !ok {
    75  			return -1, err
    76  		}
    77  		ps = exitErr.ProcessState
    78  	}
    79  	return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil
    80  }