From e98145960988a2259074ae911b6478b7a940748b Mon Sep 17 00:00:00 2001
From: Tonis Tiigi <tonistiigi@gmail.com>
Date: Wed, 28 Sep 2016 15:21:33 -0700
Subject: [PATCH] Fix missing hostname and links in exec env

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
---
 container/container_solaris.go          |  2 +-
 container/container_unix.go             |  4 ++--
 container/container_windows.go          |  2 +-
 daemon/exec.go                          | 15 ++++-----------
 daemon/oci_linux.go                     |  2 +-
 daemon/oci_windows.go                   |  2 +-
 integration-cli/docker_cli_exec_test.go |  9 +++++++++
 7 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/container/container_solaris.go b/container/container_solaris.go
index 32c0edb6c4..2abb9c2c8d 100644
--- a/container/container_solaris.go
+++ b/container/container_solaris.go
@@ -28,7 +28,7 @@ type ExitStatus struct {
 }
 
 // CreateDaemonEnvironment creates a new environment variable slice for this container.
-func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string {
+func (container *Container) CreateDaemonEnvironment(_ bool, linkedEnv []string) []string {
 	return nil
 }
 
diff --git a/container/container_unix.go b/container/container_unix.go
index 02e6ad81ba..d74ab093c8 100644
--- a/container/container_unix.go
+++ b/container/container_unix.go
@@ -52,13 +52,13 @@ type ExitStatus struct {
 // environment variables related to links.
 // Sets PATH, HOSTNAME and if container.Config.Tty is set: TERM.
 // The defaults set here do not override the values in container.Config.Env
-func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string {
+func (container *Container) CreateDaemonEnvironment(tty bool, linkedEnv []string) []string {
 	// Setup environment
 	env := []string{
 		"PATH=" + system.DefaultPathEnv,
 		"HOSTNAME=" + container.Config.Hostname,
 	}
-	if container.Config.Tty {
+	if tty {
 		env = append(env, "TERM=xterm")
 	}
 	env = append(env, linkedEnv...)
diff --git a/container/container_windows.go b/container/container_windows.go
index 93c9aaaa35..6ae1a82326 100644
--- a/container/container_windows.go
+++ b/container/container_windows.go
@@ -30,7 +30,7 @@ type ExitStatus struct {
 }
 
 // CreateDaemonEnvironment creates a new environment variable slice for this container.
-func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string {
+func (container *Container) CreateDaemonEnvironment(_ bool, linkedEnv []string) []string {
 	// because the env on the container can override certain default values
 	// we need to replace the 'env' keys where they match and append anything
 	// else.
diff --git a/daemon/exec.go b/daemon/exec.go
index 0e1d91fc34..67631333bc 100644
--- a/daemon/exec.go
+++ b/daemon/exec.go
@@ -3,7 +3,6 @@ package daemon
 import (
 	"fmt"
 	"io"
-	"runtime"
 	"strings"
 	"time"
 
@@ -18,7 +17,6 @@ import (
 	"github.com/docker/docker/libcontainerd"
 	"github.com/docker/docker/pkg/pools"
 	"github.com/docker/docker/pkg/signal"
-	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/term"
 	"github.com/docker/docker/utils"
 )
@@ -125,16 +123,11 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str
 	execConfig.Privileged = config.Privileged
 	execConfig.User = config.User
 
-	// On Windows, don't default the path, let the platform do it. Also TERM isn't meaningful
-	if runtime.GOOS != "windows" {
-		execConfig.Env = []string{
-			"PATH=" + system.DefaultPathEnv,
-		}
-		if config.Tty {
-			execConfig.Env = append(execConfig.Env, "TERM=xterm")
-		}
+	linkedEnv, err := d.setupLinkedContainers(container)
+	if err != nil {
+		return "", err
 	}
-	execConfig.Env = utils.ReplaceOrAppendEnvValues(execConfig.Env, container.Config.Env)
+	execConfig.Env = utils.ReplaceOrAppendEnvValues(container.CreateDaemonEnvironment(config.Tty, linkedEnv), execConfig.Env)
 	if len(execConfig.User) == 0 {
 		execConfig.User = container.Config.User
 	}
diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go
index a5f3b39d1e..10b5b9451f 100644
--- a/daemon/oci_linux.go
+++ b/daemon/oci_linux.go
@@ -616,7 +616,7 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
 		}
 	}
 	s.Process.Cwd = cwd
-	s.Process.Env = c.CreateDaemonEnvironment(linkedEnv)
+	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
 	s.Process.Terminal = c.Config.Tty
 	s.Hostname = c.FullHostname()
 
diff --git a/daemon/oci_windows.go b/daemon/oci_windows.go
index 4f2947cf79..c9bd0d6cec 100644
--- a/daemon/oci_windows.go
+++ b/daemon/oci_windows.go
@@ -59,7 +59,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (*libcontainerd.Spec, e
 		// as c:\. Hence, setting it to default of c:\ makes for consistency.
 		s.Process.Cwd = `C:\`
 	}
-	s.Process.Env = c.CreateDaemonEnvironment(linkedEnv)
+	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
 	s.Process.ConsoleSize.Height = c.HostConfig.ConsoleSize[0]
 	s.Process.ConsoleSize.Width = c.HostConfig.ConsoleSize[1]
 	s.Process.Terminal = c.Config.Tty
diff --git a/integration-cli/docker_cli_exec_test.go b/integration-cli/docker_cli_exec_test.go
index 69fbe2b23d..d0be69bfa0 100644
--- a/integration-cli/docker_cli_exec_test.go
+++ b/integration-cli/docker_cli_exec_test.go
@@ -520,3 +520,12 @@ func (s *DockerSuite) TestExecWindowsPathNotWiped(c *check.C) {
 	out = strings.ToLower(strings.Trim(out, "\r\n"))
 	c.Assert(out, checker.Contains, `windowspowershell\v1.0`)
 }
+
+func (s *DockerSuite) TestExecEnvLinksHost(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+	runSleepingContainer(c, "-d", "--name", "foo")
+	runSleepingContainer(c, "-d", "--link", "foo:db", "--hostname", "myhost", "--name", "bar")
+	out, _ := dockerCmd(c, "exec", "bar", "env")
+	c.Assert(out, checker.Contains, "HOSTNAME=myhost")
+	c.Assert(out, checker.Contains, "DB_NAME=/bar/db")
+}