Signed-off-by: Darren Stahl <darst@microsoft.com>
| ... | ... |
@@ -389,6 +389,8 @@ func run(b *Builder, args []string, attributes map[string]bool, original string) |
| 389 | 389 |
b.runConfig.Cmd = config.Cmd |
| 390 | 390 |
// set build-time environment for 'run'. |
| 391 | 391 |
b.runConfig.Env = append(b.runConfig.Env, cmdBuildEnv...) |
| 392 |
+ // set config as already being escaped, this prevents double escaping on windows |
|
| 393 |
+ b.runConfig.ArgsEscaped = true |
|
| 392 | 394 |
|
| 393 | 395 |
logrus.Debugf("[BUILDER] Command to be executed: %v", b.runConfig.Cmd)
|
| 394 | 396 |
|
| ... | ... |
@@ -479,7 +481,7 @@ func entrypoint(b *Builder, args []string, attributes map[string]bool, original |
| 479 | 479 |
if runtime.GOOS != "windows" {
|
| 480 | 480 |
b.runConfig.Entrypoint = stringutils.NewStrSlice("/bin/sh", "-c", parsed[0])
|
| 481 | 481 |
} else {
|
| 482 |
- b.runConfig.Entrypoint = stringutils.NewStrSlice("cmd", "/S /C", parsed[0])
|
|
| 482 |
+ b.runConfig.Entrypoint = stringutils.NewStrSlice("cmd", "/S", "/C", parsed[0])
|
|
| 483 | 483 |
} |
| 484 | 484 |
} |
| 485 | 485 |
|
| ... | ... |
@@ -181,7 +181,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 181 | 181 |
if runtime.GOOS != "windows" {
|
| 182 | 182 |
b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
|
| 183 | 183 |
} else {
|
| 184 |
- b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
|
|
| 184 |
+ b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S", "/C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
|
|
| 185 | 185 |
} |
| 186 | 186 |
defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
|
| 187 | 187 |
|
| ... | ... |
@@ -48,6 +48,7 @@ type Command struct {
|
| 48 | 48 |
LayerFolder string `json:"layer_folder"` // Layer folder for a command |
| 49 | 49 |
LayerPaths []string `json:"layer_paths"` // Layer paths for a command |
| 50 | 50 |
Isolation runconfig.IsolationLevel `json:"isolation"` // Isolation level for the container |
| 51 |
+ ArgsEscaped bool `json:"args_escaped"` // True if args are already escaped |
|
| 51 | 52 |
} |
| 52 | 53 |
|
| 53 | 54 |
// ExitStatus provides exit reasons for a container. |
| 54 | 55 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,36 @@ |
| 0 |
+//+build windows |
|
| 1 |
+ |
|
| 2 |
+package windows |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "errors" |
|
| 6 |
+ "syscall" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/docker/docker/daemon/execdriver" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// createCommandLine creates a command line from the Entrypoint and args |
|
| 13 |
+// of the ProcessConfig. It escapes the arguments if they are not already |
|
| 14 |
+// escaped |
|
| 15 |
+func createCommandLine(processConfig *execdriver.ProcessConfig, alreadyEscaped bool) (commandLine string, err error) {
|
|
| 16 |
+ // While this should get caught earlier, just in case, validate that we |
|
| 17 |
+ // have something to run. |
|
| 18 |
+ if processConfig.Entrypoint == "" {
|
|
| 19 |
+ return "", errors.New("No entrypoint specified")
|
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ // Build the command line of the process |
|
| 23 |
+ commandLine = processConfig.Entrypoint |
|
| 24 |
+ logrus.Debugf("Entrypoint: %s", processConfig.Entrypoint)
|
|
| 25 |
+ for _, arg := range processConfig.Arguments {
|
|
| 26 |
+ logrus.Debugf("appending %s", arg)
|
|
| 27 |
+ if !alreadyEscaped {
|
|
| 28 |
+ arg = syscall.EscapeArg(arg) |
|
| 29 |
+ } |
|
| 30 |
+ commandLine += " " + arg |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ logrus.Debugf("commandLine: %s", commandLine)
|
|
| 34 |
+ return commandLine, nil |
|
| 35 |
+} |
| ... | ... |
@@ -3,7 +3,6 @@ |
| 3 | 3 |
package windows |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
- "errors" |
|
| 7 | 6 |
"fmt" |
| 8 | 7 |
|
| 9 | 8 |
"github.com/Sirupsen/logrus" |
| ... | ... |
@@ -34,21 +33,11 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo |
| 34 | 34 |
// Configure the environment for the process // Note NOT c.ProcessConfig.Tty |
| 35 | 35 |
createProcessParms.Environment = setupEnvironmentVariables(processConfig.Env) |
| 36 | 36 |
|
| 37 |
- // While this should get caught earlier, just in case, validate that we |
|
| 38 |
- // have something to run. |
|
| 39 |
- if processConfig.Entrypoint == "" {
|
|
| 40 |
- err = errors.New("No entrypoint specified")
|
|
| 41 |
- logrus.Error(err) |
|
| 42 |
- return -1, err |
|
| 43 |
- } |
|
| 37 |
+ createProcessParms.CommandLine, err = createCommandLine(&c.ProcessConfig, c.ArgsEscaped) |
|
| 44 | 38 |
|
| 45 |
- // Build the command line of the process |
|
| 46 |
- createProcessParms.CommandLine = processConfig.Entrypoint |
|
| 47 |
- for _, arg := range processConfig.Arguments {
|
|
| 48 |
- logrus.Debugln("appending ", arg)
|
|
| 49 |
- createProcessParms.CommandLine += " " + arg |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return -1, err |
|
| 50 | 41 |
} |
| 51 |
- logrus.Debugln("commandLine: ", createProcessParms.CommandLine)
|
|
| 52 | 42 |
|
| 53 | 43 |
// Start the command running in the container. |
| 54 | 44 |
pid, stdin, stdout, stderr, rc, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !processConfig.Tty, createProcessParms) |
| ... | ... |
@@ -4,13 +4,11 @@ package windows |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"encoding/json" |
| 7 |
- "errors" |
|
| 8 | 7 |
"fmt" |
| 9 | 8 |
"os" |
| 10 | 9 |
"path/filepath" |
| 11 | 10 |
"strconv" |
| 12 | 11 |
"strings" |
| 13 |
- "syscall" |
|
| 14 | 12 |
|
| 15 | 13 |
"github.com/Sirupsen/logrus" |
| 16 | 14 |
"github.com/docker/docker/daemon/execdriver" |
| ... | ... |
@@ -279,21 +277,11 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd |
| 279 | 279 |
// Configure the environment for the process |
| 280 | 280 |
createProcessParms.Environment = setupEnvironmentVariables(c.ProcessConfig.Env) |
| 281 | 281 |
|
| 282 |
- // This should get caught earlier, but just in case - validate that we |
|
| 283 |
- // have something to run |
|
| 284 |
- if c.ProcessConfig.Entrypoint == "" {
|
|
| 285 |
- err = errors.New("No entrypoint specified")
|
|
| 286 |
- logrus.Error(err) |
|
| 287 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 288 |
- } |
|
| 282 |
+ createProcessParms.CommandLine, err = createCommandLine(&c.ProcessConfig, c.ArgsEscaped) |
|
| 289 | 283 |
|
| 290 |
- // Build the command line of the process |
|
| 291 |
- createProcessParms.CommandLine = c.ProcessConfig.Entrypoint |
|
| 292 |
- for _, arg := range c.ProcessConfig.Arguments {
|
|
| 293 |
- logrus.Debugln("appending ", arg)
|
|
| 294 |
- createProcessParms.CommandLine += " " + syscall.EscapeArg(arg) |
|
| 284 |
+ if err != nil {
|
|
| 285 |
+ return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 295 | 286 |
} |
| 296 |
- logrus.Debugf("CommandLine: %s", createProcessParms.CommandLine)
|
|
| 297 | 287 |
|
| 298 | 288 |
// Start the command running in the container. |
| 299 | 289 |
pid, stdin, stdout, stderr, _, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !c.ProcessConfig.Tty, createProcessParms) |
| ... | ... |
@@ -30,6 +30,7 @@ type Config struct {
|
| 30 | 30 |
StdinOnce bool // If true, close stdin after the 1 attached client disconnects. |
| 31 | 31 |
Env []string // List of environment variable to set in the container |
| 32 | 32 |
Cmd *stringutils.StrSlice // Command to run when starting the container |
| 33 |
+ ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific) |
|
| 33 | 34 |
Image string // Name of the image as it was passed by the operator (eg. could be symbolic) |
| 34 | 35 |
Volumes map[string]struct{} // List of volumes (mounts) used for the container
|
| 35 | 36 |
WorkingDir string // Current directory (PWD) in the command will be launched |