Win32OperatingSystem.st
branchjv
changeset 23097 d619cf99365a
parent 23091 817fd8c6e4c5
child 23101 cd0581d5639b
--- a/Win32OperatingSystem.st	Tue Dec 12 08:57:23 2017 +0000
+++ b/Win32OperatingSystem.st	Thu Jan 11 23:40:14 2018 +0000
@@ -1609,7 +1609,7 @@
 getTTYAttributes: fd
 	OsError raiseErrorString: 'TTYs / PTYs not supported on Windows'
 
-!	
+!
 
 isTTY: fd                                                                                                     
     "Return true, if given filedescriptor refers to a character device (console). See _isatty()                                  
@@ -3783,66 +3783,77 @@
     "Modified: / 11-02-2007 / 20:51:08 / cg"
 !
 
-exec:aCommandPath withArguments:argString environment:environment fileDescriptors:fdArray fork:doFork
-	newPgrp:newPgrp inDirectory:aDirectory
-	showWindow:showWindowBooleanOrNil
+exec:commandPath withArguments:argumentsOrCommandLine environment:environment fileDescriptors:fdArray fork:doFork
+        newPgrp:newPgrp inDirectory:aDirectory
+        showWindow:showWindowBooleanOrNil
 
     "Internal lowLevel entry for combined fork & exec for WIN32
 
      If fork is false (chain a command):
-	 execute the OS command specified by the argument, aCommandPath, with
-	 arguments in argArray (no arguments, if nil).
-	 If successful, this method does not return and smalltalk is gone.
-	 If not successful, it does return.
-	 Normal use is with forkForCommand.
+         execute the OS command specified by the argument, aCommandPath, with
+         arguments in argArray (no arguments, if nil).
+         If successful, this method does not return and smalltalk is gone.
+         If not successful, it does return.
+         Normal use is with forkForCommand.
 
      If fork is true (subprocess command execution):
-	fork a child to do the above.
-	The Win32ProcessHandle of the child process is returned; nil if the fork failed.
+        fork a child to do the above.
+        The Win32ProcessHandle of the child process is returned; nil if the fork failed.
 
      fdArray contains the filedescriptors, to be used for the child (if fork is true).
-	fdArray[1] = 15 -> use fd 15 as stdin.
-	If an element of the array is set to nil, the corresponding filedescriptor
-	will be closed for the child.
-	fdArray[0] == StdIn for child
-	fdArray[1] == StdOut for child
-	fdArray[2] == StdErr for child
+        fdArray[1] = 15 -> use fd 15 as stdin.
+        If an element of the array is set to nil, the corresponding filedescriptor
+        will be closed for the child.
+        fdArray[0] == StdIn for child
+        fdArray[1] == StdOut for child
+        fdArray[2] == StdErr for child
 
      NOTE that in WIN32 the fds are HANDLES.
 
      If newPgrp is true, the subprocess will be established in a new process group.
-	The processgroup will be equal to id.
-	newPgrp is not used on WIN32 and VMS systems.
+        The processgroup will be equal to id.
+        newPgrp is not used on WIN32 and VMS systems.
 
      showWindowOrBoolean may be:
-	true  - a window is shown on start of the command
-	false - the command window is hidden
-	nil   - the nCmdShown parameter of the commans's winmain function determins,
-		if a window is shown.
-	#default
-	      - same as nil
-    "
-
-    |dirPath rslt|
-
+        true  - a window is shown on start of the command
+        false - the command window is hidden
+        nil   - the nCmdShown parameter of the commans's winmain function determins,
+                if a window is shown.
+        #default
+              - same as nil
+    "
+
+    |commandLine dirPath rslt|
+
+    argumentsOrCommandLine isString ifTrue:[ 
+        commandLine := argumentsOrCommandLine
+    ] ifFalse:[
+        argumentsOrCommandLine isSequenceable ifTrue:[ 
+            commandLine := String streamContents:[:s|
+                argumentsOrCommandLine 
+                    do:[:p |self quoteCommandParameter: p on: s]
+                    separatedBy:[ s space ]
+            ].
+        ].
+    ].
     aDirectory notNil ifTrue:[
-	dirPath := aDirectory asFilename asAbsoluteFilename osNameForDirectory.
-	(dirPath endsWith:':') ifTrue:[
-	    dirPath := dirPath , '\'.
-	].
+        dirPath := aDirectory asFilename asAbsoluteFilename osNameForDirectory.
+        (dirPath endsWith:':') ifTrue:[
+            dirPath := dirPath , '\'.
+        ].
     ].
 
     rslt := self
-	primExec:aCommandPath
-	commandLine:argString
-	environment:environment
-	fileDescriptors:fdArray
-	fork:doFork
-	newPgrp:newPgrp
-	inPath:dirPath
-	createFlags:nil
-	inheritHandles:true
-	showWindow:showWindowBooleanOrNil.
+        primExec:commandPath
+        commandLine:commandLine
+        environment:environment
+        fileDescriptors:fdArray
+        fork:doFork
+        newPgrp:newPgrp
+        inPath:dirPath
+        createFlags:nil
+        inheritHandles:true
+        showWindow:showWindowBooleanOrNil.
 
 "/ 'created ' print. cmdLine print. ' -> ' print. rslt printCR.
     ^ rslt
@@ -3850,6 +3861,7 @@
     "Modified: / 31-01-1998 / 10:54:24 / md"
     "Modified: / 15-05-1999 / 18:07:51 / cg"
     "Modified (comment): / 18-10-2016 / 16:00:26 / cg"
+    "Modified: / 11-01-2018 / 23:31:55 / jv"
 !
 
 getStatusOfProcess:aProcessId
@@ -10653,6 +10665,50 @@
     "
 	self primExpandEnvironmentStringsW:'%ProgramFiles%\test\x' asUnicodeString into:(Unicode16String new:256) inspect size:256
     "
+!
+
+quoteCommandParameter: parameter on: stream
+    "Quotes the parameter as neccesary on Windows"
+
+    "/ Adapted version of ArgvQuote,
+    "/ see http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
+
+    | parameterS |
+
+    stream nextPut: $".
+    parameterS := parameter readStream.
+    [ parameterS atEnd ] whileFalse:[
+        | numBackSlashes |
+
+        numBackSlashes := 0.
+
+        [ parameterS atEnd not and:[ parameterS peek == $\ ] ] whileTrue:[
+            numBackSlashes := numBackSlashes + 1.
+            parameterS next.
+        ].
+        parameterS atEnd ifTrue:[
+            "/ Escape all backslashes, but let the terminating
+            "/ double quotation mark we add below be interpreted
+            "/ as a metacharacter.
+            stream next: numBackSlashes * 2 put: $\
+        ] ifFalse:[
+            parameterS peek == $" ifTrue:[
+                "/ Escape all backslashes and the following
+                "/ double quotation mark.
+                stream next: numBackSlashes * 2 put: $\.
+                stream nextPut: $\.
+                stream nextPut: $".
+            ] ifFalse:[
+                "/ Backslashes aren't special here.
+                stream next: numBackSlashes put: $\.               
+                stream nextPut: parameterS peek.
+            ].
+            parameterS next.
+        ].
+    ].
+    stream nextPut: $".
+
+    "Created: / 11-01-2018 / 23:24:07 / jv"
 ! !
 
 !Win32OperatingSystem class methodsFor:'regional settings'!