Skip to content

Commit deb4d95

Browse files
author
John Howard
committed
Windows:Have native CommandLine in Process
Signed-off-by: John Howard <[email protected]> This adds a new field `CommandLine` in the `Process` structure for use on Windows. A Windows runtime will check this first and use it as-is when launching WCOW processes in a container. If omitted, the Windows runtime will fall back to the previous behaviour of escaping (eg Windows.EscapeArg in golang) each of the `args` array elements, and space-concatenating them. The reason for this change is to avoid loss of fidelity for launching processes. One such example is the following: `cmd /S /C mkdir "c:/foo"` When parsed into a JSON array such as `Args`, it becomes 5 elements - cmd - /S - /C - mkdir - c:/foo Here, note the lost information being the double-quotes around `c:/foo`. When using the required contenation, space separation required on Windows, (https://github.com/golang/sys/blob/c4afb3effaa53fd9a06ca61262dc7ce8df4c081b/windows/exec_windows.go#L9-L18), this becomes the following command line: `cmd /S /C mkdir c:/foo` When the double-quotes are missing, mkdir would fail, but with the double-quotes, it succeeds as expected: ``` C:\>cmd /s /c mkdir c:/foo The syntax of the command is incorrect. C:\>cmd /s /c mkdir "c:/foo" C:\> ``` The addition of a full `commandLine` in Process for use on Windows alleviates issues where fidelity can be lost. Some further background: For historical reasons, Windows only has native support for launching processes using a command line. It does not support an argument array as per Linux. See the `CreateProcess` API documentation on MSDN. What happens under the covers is that prior to invoking a programs main, the language runtime will convert the command line to a set of argv[] suach as in the C-style `int main(int argc, char* argv), or the golang `os.Args` prior to the programs `main` being invoked, using Windows- specific rules. In go, that's the `commandLineToArgv` function which is called in the init() function of the os package https://github.com/golang/go/blob/ff7b245a31394b700a252fd547cf16ad0ad838b6/src/os/exec_windows.go#L100, In the Microsoft C++ startup code, it does exactly the same processing as documented here prior to invoking main itself: https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments?view=vs-2017. The processing it describes is documented at https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx and https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw Some related links which provide a lot more information about the very specific (and unique to Windows) command line escaping rules, and handling of them are below: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ https://stackoverflow.com/questions/31838469/how-do-i-convert-argv-to-lpcommandline-parameter-of-createprocess https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments?view=vs-2017
1 parent 1722abf commit deb4d95

File tree

3 files changed

+12
-5
lines changed

3 files changed

+12
-5
lines changed

config.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,11 @@ For POSIX platforms the `mounts` structure has the following fields:
155155
* **`cwd`** (string, REQUIRED) is the working directory that will be set for the executable.
156156
This value MUST be an absolute path.
157157
* **`env`** (array of strings, OPTIONAL) with the same semantics as [IEEE Std 1003.1-2008's `environ`][ieee-1003.1-2008-xbd-c8.1].
158-
* **`args`** (array of strings, REQUIRED) with similar semantics to [IEEE Std 1003.1-2008 `execvp`'s *argv*][ieee-1003.1-2008-functions-exec].
159-
This specification extends the IEEE standard in that at least one entry is REQUIRED, and that entry is used with the same semantics as `execvp`'s *file*.
158+
* **`args`** (array of strings, OPTIONAL) with similar semantics to [IEEE Std 1003.1-2008 `execvp`'s *argv*][ieee-1003.1-2008-functions-exec].
159+
This specification extends the IEEE standard in that at least one entry is REQUIRED (non-Windows), and that entry is used with the same semantics as `execvp`'s *file*. This field is OPTIONAL on Windows, and `commandLine` is REQUIRED if this field is omitted.
160+
* **`commandLine`** (string, OPTIONAL) specifies the full command line to be executed on Windows.
161+
This is the preferred means of supplying the command line on Windows. If omitted, the runtime will fall back to escaping and concatenating fields from `args` before making the system call into Windows.
162+
160163

161164
### <a name="configPOSIXProcess" />POSIX process
162165

schema/config-schema.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@
5050
"process": {
5151
"type": "object",
5252
"required": [
53-
"cwd",
54-
"args"
53+
"cwd"
5554
],
5655
"properties": {
5756
"args": {
5857
"$ref": "defs.json#/definitions/ArrayOfStrings"
5958
},
59+
"commandLine": {
60+
"type": "string"
61+
},
6062
"consoleSize": {
6163
"type": "object",
6264
"required": [

specs-go/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ type Process struct {
3838
// User specifies user information for the process.
3939
User User `json:"user"`
4040
// Args specifies the binary and arguments for the application to execute.
41-
Args []string `json:"args"`
41+
Args []string `json:"args,omitempty"`
42+
// CommandLine specifies the full command line for the application to execute on Windows.
43+
CommandLine string `json:"commandLine,omitempty" platform:"windows"`
4244
// Env populates the process environment for the process.
4345
Env []string `json:"env,omitempty"`
4446
// Cwd is the current working directory for the process and must be

0 commit comments

Comments
 (0)