Environment in #executeCommand:...
--- a/AbstractOperatingSystem.st Thu Apr 03 10:45:30 2003 +0200
+++ b/AbstractOperatingSystem.st Thu Apr 03 14:48:50 2003 +0200
@@ -731,151 +731,6 @@
self subclassResponsibility
!
-exec:aCommandPath withArguments:argArray
- "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.
- Can be used on UNIX with fork or on other systems to chain to another program."
-
- ^ self
- exec:aCommandPath
- withArguments:argArray
- environment:nil
- fileDescriptors:#(0 1 2)
- fork:false
- newPgrp:false
- inDirectory:nil
-
- "/ never reached ...
-
- "Modified: / 12.11.1998 / 14:44:26 / cg"
-!
-
-exec:aCommandPath withArguments:argArray environment:env fileDescriptors:fds fork:doFork newPgrp:newGrp inDirectory:aDirectory
- "execute an OS command"
-
- ^ self subclassResponsibility
-
- "Created: / 12.11.1998 / 14:46:15 / cg"
-!
-
-exec:aCommandPath withArguments:argArray fileDescriptors:fileDescriptors fork:doFork newPgrp:newPgrp inDirectory:aDirectory
- ^ self
- exec:aCommandPath
- withArguments:argArray
- environment:nil
- fileDescriptors:fileDescriptors
- fork:doFork
- newPgrp:newPgrp
- inDirectory:aDirectory
-!
-
-exec:aCommandPath withArguments:argArray fork:doFork
- "execute an OS command without I/O redirection.
- The command reads its input and writes its output
- from/to whatever terminal device ST/X was started
- (typically, the terminal window)"
-
- ^ self
- exec:aCommandPath
- withArguments:argArray
- environment:nil
- fileDescriptors:#(0 1 2)
- fork:doFork
- newPgrp:false
- inDirectory:nil
-
- "
- |id|
-
- id := OperatingSystem fork.
- id == 0 ifTrue:[
- 'I am the child'.
- OperatingSystem
- exec:'/bin/ls'
- withArguments:#('ls' '/tmp')
- fork:false.
- 'not reached'.
- ]
- "
-
- "
- |id|
-
- id := OperatingSystem fork.
- id == 0 ifTrue:[
- 'I am the child'.
- OperatingSystem
- exec:'/bin/sh'
- withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
- fork:false.
- 'not reached'.
- ].
- id printNL.
- (Delay forSeconds:3.5) wait.
- 'killing ...' printNL.
- OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
- OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
- "
-
- "Modified: / 15.7.1997 / 15:54:32 / stefan"
- "Modified: / 12.11.1998 / 14:44:46 / cg"
-!
-
-exec:aCommandPath withArguments:argArray fork:doFork inDirectory:aDirectory
- "execute an OS command without I/O redirection.
- The command reads its input and writes its output
- from/to whatever terminal device ST/X was started
- (typically, the terminal window)"
-
- ^ self
- exec:aCommandPath
- withArguments:argArray
- environment:nil
- fileDescriptors:#(0 1 2)
- fork:doFork
- newPgrp:false
- inDirectory:aDirectory
-
- "
- |id|
-
- id := OperatingSystem fork.
- id == 0 ifTrue:[
- 'I am the child'.
- OperatingSystem
- exec:'/bin/ls'
- withArguments:#('ls' '/tmp')
- fork:false.
- 'not reached'.
- ]
- "
-
- "
- |id|
-
- id := OperatingSystem fork.
- id == 0 ifTrue:[
- 'I am the child'.
- OperatingSystem
- exec:'/bin/sh'
- withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
- fork:false.
- 'not reached'.
- ].
- id printNL.
- (Delay forSeconds:3.5) wait.
- 'killing ...' printNL.
- OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
- OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
- "
-
- "Created: / 28.1.1998 / 14:14:03 / md"
- "Modified: / 28.1.1998 / 14:14:45 / md"
- "Modified: / 12.11.1998 / 14:45:06 / cg"
-!
-
executableFileExtensions
"return a collection of extensions for executable program files.
Only req'd for msdos & vms like systems ..."
@@ -991,6 +846,203 @@
"Modified: / 10.11.1998 / 20:54:37 / cg"
!
+executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream
+ errorTo:anErrStream auxFrom:anAuxStream environment:environmentDictionary
+ inDirectory:dirOrNil lineWise:lineWise onError:aBlock
+
+ "execute the unix command specified by the argument, aCommandString.
+ The commandString is passed to a shell for execution - see the description of
+ 'sh -c' in your UNIX manual.
+ Return true if successful, or the value of aBlock if not.
+ If not successfull, aBlock is called with an OsProcessStatus
+ (containing the exit status) as argument.
+ The given in, out and err streams may be arbitrary (Smalltalk-) streams;
+ if any is not an external stream (which is required by the command),
+ extra pipes and shuffler processes are created, which stuff the data into
+ those internal stream(s).
+ Nil stream args will execute the command connected to ST/X's standard input, output or
+ error resp. - i.e. usually, i/o will be from/to the terminal"
+
+ |pid exitStatus sema pIn pOut pErr pAux externalInStream externalOutStream externalErrStream externalAuxStream
+ shuffledInStream shuffledOutStream shuffledErrStream shuffledAuxStream
+ inputShufflerProcess outputShufflerProcess errorShufflerProcess auxShufflerProcess stopShufflers
+ inStreamToClose outStreamToClose errStreamToClose auxStreamToClose terminateLock|
+
+ terminateLock := Semaphore forMutualExclusion.
+ ((externalInStream := anInStream) notNil
+ and:[externalInStream isExternalStream not]) ifTrue:[
+ pIn := ExternalStream makePipe.
+ inStreamToClose := externalInStream := pIn at:1.
+ shuffledInStream := pIn at:2.
+ lineWise ifTrue:[shuffledInStream buffered:false].
+
+ "/ start a reader process, shuffling data from the given
+ "/ inStream to the pipe (which is connected to the commands input)
+ inputShufflerProcess := [
+ [
+ [anInStream atEnd] whileFalse:[
+ self shuffleFrom:anInStream to:shuffledInStream lineWise:lineWise.
+ shuffledInStream flush
+ ]
+ ] ensure:[
+ shuffledInStream close
+ ]
+ ] forkNamed:'cmd input shuffler'.
+ ].
+ ((externalOutStream := anOutStream) notNil
+ and:[externalOutStream isExternalStream not]) ifTrue:[
+ pOut := ExternalStream makePipe.
+ shuffledOutStream := (pOut at:1).
+ outStreamToClose := externalOutStream := pOut at:2.
+ lineWise ifTrue:[shuffledOutStream buffered:false].
+ outputShufflerProcess :=
+ [
+ self shuffleAllFrom:shuffledOutStream to:anOutStream lineWise:lineWise lockWith:terminateLock.
+ ] forkNamed:'cmd output shuffler'.
+ ].
+ (externalErrStream := anErrStream) notNil ifTrue:[
+ anErrStream == anOutStream ifTrue:[
+ externalErrStream := externalOutStream
+ ] ifFalse:[
+ anErrStream isExternalStream ifFalse:[
+ pErr := ExternalStream makePipe.
+ shuffledErrStream := (pErr at:1).
+ errStreamToClose := externalErrStream := pErr at:2.
+
+ lineWise ifTrue:[shuffledErrStream buffered:false].
+ errorShufflerProcess :=
+ [
+ self shuffleAllFrom:shuffledErrStream to:anErrStream lineWise:lineWise lockWith:terminateLock.
+ ] forkNamed:'cmd err-output shuffler'.
+ ]
+ ]
+ ].
+ ((externalAuxStream := anAuxStream) notNil
+ and:[externalAuxStream isExternalStream not]) ifTrue:[
+ pAux := ExternalStream makePipe.
+ auxStreamToClose := externalAuxStream := pAux at:1.
+ shuffledAuxStream := pAux at:2.
+
+ "/ start a reader process, shuffling data from the given
+ "/ auxStream to the pipe (which is connected to the commands aux)
+ auxShufflerProcess := [
+ [
+ [anAuxStream atEnd] whileFalse:[
+ self shuffleFrom:anAuxStream to:shuffledAuxStream lineWise:false.
+ shuffledAuxStream flush
+ ]
+ ] ensure:[
+ shuffledAuxStream close
+ ]
+ ] forkNamed:'cmd aux shuffler'.
+ ].
+
+ sema := Semaphore new name:'OS command wait'.
+ pid := Processor
+ monitor:[
+ self
+ startProcess:aCommandString
+ inputFrom:externalInStream
+ outputTo:externalOutStream
+ errorTo:externalErrStream
+ auxFrom:externalAuxStream
+ environment:environmentDictionary
+ inDirectory:dirOrNil
+ ]
+ action:[:status |
+ status stillAlive ifFalse:[
+ exitStatus := status.
+ sema signal.
+ self closePid:pid
+ ]
+ ].
+
+ inStreamToClose notNil ifTrue:[
+ inStreamToClose close
+ ].
+ errStreamToClose notNil ifTrue:[
+ errStreamToClose close
+ ].
+ outStreamToClose notNil ifTrue:[
+ outStreamToClose close
+ ].
+ auxStreamToClose notNil ifTrue:[
+ auxStreamToClose close
+ ].
+
+ stopShufflers := [
+ inputShufflerProcess notNil ifTrue:[
+ terminateLock critical:[inputShufflerProcess terminate].
+ inputShufflerProcess waitUntilTerminated
+ ].
+ auxShufflerProcess notNil ifTrue:[
+ terminateLock critical:[auxShufflerProcess terminate].
+ auxShufflerProcess waitUntilTerminated
+ ].
+ outputShufflerProcess notNil ifTrue:[
+ terminateLock critical:[outputShufflerProcess terminate].
+ outputShufflerProcess waitUntilTerminated.
+ self shuffleRestFrom:shuffledOutStream to:anOutStream lineWise:lineWise.
+ shuffledOutStream close.
+ ].
+ errorShufflerProcess notNil ifTrue:[
+ terminateLock critical:[errorShufflerProcess terminate].
+ errorShufflerProcess waitUntilTerminated.
+ self shuffleRestFrom:shuffledErrStream to:anErrStream lineWise:lineWise.
+ shuffledErrStream close.
+ ].
+ ].
+
+ pid notNil ifTrue:[
+ [
+ sema wait.
+ ] ifCurtailed:[
+ "/ terminate the os-command (and all of its forked commands)
+ self terminateProcessGroup:pid.
+ self terminateProcess:pid.
+ self closePid:pid.
+ stopShufflers value.
+ ]
+ ] ifFalse:[
+ exitStatus := self osProcessStatusClass processCreationFailure
+ ].
+ stopShufflers value.
+ exitStatus success ifFalse:[
+ ^ aBlock value:exitStatus
+ ].
+ ^ true
+
+ "
+ |outStream errStream|
+
+ outStream := '' writeStream.
+
+ OperatingSystem executeCommand:'ls -l'
+ inputFrom:'abc' readStream
+ outputTo:outStream
+ errorTo:nil
+ inDirectory:nil
+ lineWise:true
+ onError:[:exitStatus | ^ false].
+ outStream contents
+ "
+
+ "
+ |outStream errStream|
+
+ outStream := '' writeStream.
+
+ OperatingSystem executeCommand:'gpg -s --batch --no-tty --passphrase-fd 0 /tmp/passwd'
+ inputFrom:'bla' readStream
+ outputTo:outStream
+ errorTo:nil
+ inDirectory:nil
+ lineWise:true
+ onError:[:exitStatus | false].
+ outStream contents
+ "
+!
+
executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream errorTo:anErrStream auxFrom:anAuxStream inDirectory:dirOrNil lineWise:lineWise onError:aBlock
"execute the unix command specified by the argument, aCommandString.
The commandString is passed to a shell for execution - see the description of
@@ -1461,24 +1513,6 @@
"Created: / 10.11.1998 / 21:05:45 / cg"
!
-fork
- "fork a new (HEAVY-weight) unix process.
- Not supported with MSDOS & VMS systems.
- Dont confuse this with Block>>fork, which creates
- lightweight smalltalk processes. This method will return
- 0 to the child process, and a non-zero number (which is the childs
- unix-process-id) to the parent (original) process.
-
- In normal situations, you dont need to use this low level entry; see
- #startProcess: and #executCommand: for higher level interfaces."
-
- "/
- "/ not supported by OS
- "/
-
- ^ UnsupportedOperationSignal raise
-!
-
getCommandOutputFrom:aCommand
"execute a simple command (such as hostname) and
return the commands first line of output as a string (forget stdErr).
@@ -1574,15 +1608,6 @@
!
-getVMSSymbol:aSymbolString
- "get a symbols value, or nil if there is none"
-
- ^ nil
-
- "Created: / 5.6.1998 / 19:02:50 / cg"
- "Modified: / 5.6.1998 / 19:03:15 / cg"
-!
-
nameOfSTXExecutable
"return the name of the running ST/X executable program.
Usually, 'stx' is returned - but may be different for
@@ -1616,7 +1641,174 @@
"
OperatingSystem pathOfSTXExecutable
"
-!
+! !
+
+!AbstractOperatingSystem class methodsFor:'executing OS commands - low level'!
+
+exec:aCommandPath withArguments:argArray
+ "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.
+ Can be used on UNIX with fork or on other systems to chain to another program."
+
+ ^ self
+ exec:aCommandPath
+ withArguments:argArray
+ environment:nil
+ fileDescriptors:#(0 1 2)
+ fork:false
+ newPgrp:false
+ inDirectory:nil
+
+ "/ never reached ...
+
+ "Modified: / 12.11.1998 / 14:44:26 / cg"
+!
+
+exec:aCommandPath withArguments:argArray environment:env fileDescriptors:fds fork:doFork newPgrp:newGrp inDirectory:aDirectory
+ "execute an OS command"
+
+ ^ self subclassResponsibility
+
+ "Created: / 12.11.1998 / 14:46:15 / cg"
+!
+
+exec:aCommandPath withArguments:argArray fileDescriptors:fileDescriptors fork:doFork newPgrp:newPgrp inDirectory:aDirectory
+ ^ self
+ exec:aCommandPath
+ withArguments:argArray
+ environment:nil
+ fileDescriptors:fileDescriptors
+ fork:doFork
+ newPgrp:newPgrp
+ inDirectory:aDirectory
+!
+
+exec:aCommandPath withArguments:argArray fork:doFork
+ "execute an OS command without I/O redirection.
+ The command reads its input and writes its output
+ from/to whatever terminal device ST/X was started
+ (typically, the terminal window)"
+
+ ^ self
+ exec:aCommandPath
+ withArguments:argArray
+ environment:nil
+ fileDescriptors:#(0 1 2)
+ fork:doFork
+ newPgrp:false
+ inDirectory:nil
+
+ "
+ |id|
+
+ id := OperatingSystem fork.
+ id == 0 ifTrue:[
+ 'I am the child'.
+ OperatingSystem
+ exec:'/bin/ls'
+ withArguments:#('ls' '/tmp')
+ fork:false.
+ 'not reached'.
+ ]
+ "
+
+ "
+ |id|
+
+ id := OperatingSystem fork.
+ id == 0 ifTrue:[
+ 'I am the child'.
+ OperatingSystem
+ exec:'/bin/sh'
+ withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
+ fork:false.
+ 'not reached'.
+ ].
+ id printNL.
+ (Delay forSeconds:3.5) wait.
+ 'killing ...' printNL.
+ OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
+ OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
+ "
+
+ "Modified: / 15.7.1997 / 15:54:32 / stefan"
+ "Modified: / 12.11.1998 / 14:44:46 / cg"
+!
+
+exec:aCommandPath withArguments:argArray fork:doFork inDirectory:aDirectory
+ "execute an OS command without I/O redirection.
+ The command reads its input and writes its output
+ from/to whatever terminal device ST/X was started
+ (typically, the terminal window)"
+
+ ^ self
+ exec:aCommandPath
+ withArguments:argArray
+ environment:nil
+ fileDescriptors:#(0 1 2)
+ fork:doFork
+ newPgrp:false
+ inDirectory:aDirectory
+
+ "
+ |id|
+
+ id := OperatingSystem fork.
+ id == 0 ifTrue:[
+ 'I am the child'.
+ OperatingSystem
+ exec:'/bin/ls'
+ withArguments:#('ls' '/tmp')
+ fork:false.
+ 'not reached'.
+ ]
+ "
+
+ "
+ |id|
+
+ id := OperatingSystem fork.
+ id == 0 ifTrue:[
+ 'I am the child'.
+ OperatingSystem
+ exec:'/bin/sh'
+ withArguments:#('sh' '-c' 'sleep 2;echo 1;sleep 2;echo 2')
+ fork:false.
+ 'not reached'.
+ ].
+ id printNL.
+ (Delay forSeconds:3.5) wait.
+ 'killing ...' printNL.
+ OperatingSystem sendSignal:(OperatingSystem sigTERM) to:id.
+ OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id
+ "
+
+ "Created: / 28.1.1998 / 14:14:03 / md"
+ "Modified: / 28.1.1998 / 14:14:45 / md"
+ "Modified: / 12.11.1998 / 14:45:06 / cg"
+!
+
+fork
+ "fork a new (HEAVY-weight) unix process.
+ Not supported with MSDOS & VMS systems.
+ Dont confuse this with Block>>fork, which creates
+ lightweight smalltalk processes. This method will return
+ 0 to the child process, and a non-zero number (which is the childs
+ unix-process-id) to the parent (original) process.
+
+ In normal situations, you dont need to use this low level entry; see
+ #startProcess: and #executCommand: for higher level interfaces."
+
+ "/
+ "/ not supported by OS
+ "/
+
+ ^ UnsupportedOperationSignal raise
+! !
+
+!AbstractOperatingSystem class methodsFor:'executing OS commands - private'!
startProcess:aCommandString
"start executing the OS command as specified by the argument, aCommandString
@@ -2882,6 +3074,15 @@
"
OperatingSystem exitWithCoreDump - dont evaluate this
"
+!
+
+getVMSSymbol:aSymbolString
+ "get a symbols value, or nil if there is none"
+
+ ^ nil
+
+ "Created: / 5.6.1998 / 19:02:50 / cg"
+ "Modified: / 5.6.1998 / 19:03:15 / cg"
! !
!AbstractOperatingSystem class methodsFor:'os queries'!
@@ -4430,7 +4631,7 @@
!AbstractOperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.89 2003-03-26 13:14:53 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.90 2003-04-03 12:47:52 stefan Exp $'
! !
AbstractOperatingSystem initialize!
--- a/UnixOperatingSystem.st Thu Apr 03 10:45:30 2003 +0200
+++ b/UnixOperatingSystem.st Thu Apr 03 14:48:50 2003 +0200
@@ -3296,7 +3296,9 @@
"Modified: / 5.6.1998 / 17:40:48 / cg"
!
-exec:aCommandPath withArguments:argColl environment:env fileDescriptors:fdColl fork:doFork newPgrp:newPgrp inDirectory:aDirectory
+exec:aCommandPath withArguments:argColl environment:environmenDictionary
+ fileDescriptors:fdColl fork:doFork newPgrp:newPgrp inDirectory:aDirectory
+
"Internal lowLevel entry for combined fork & exec;
If fork is false (chain a command):
@@ -3324,7 +3326,7 @@
The processgroup will be equal to id.
newPgrp is not used on WIN32 and VMS systems.
- env specifies environment variables which are passed differently from
+ environmenDictionary specifies environment variables which are passed differently from
the current environment. If non-nil, it must be a dictionary providing
key-value pairs for changed/added environment variables.
To pass a variable as empty (i.e. unset), pass a nil value.
@@ -3336,9 +3338,9 @@
|envPairs argArray fdArray dirName|
- env notNil ifTrue:[
+ environmenDictionary notNil ifTrue:[
envPairs := OrderedCollection new.
- env keysAndValuesDo:[:key :val |
+ environmenDictionary keysAndValuesDo:[:key :val |
envPairs add:key; add:val
].
envPairs := envPairs asArray.
@@ -3771,7 +3773,10 @@
"Modified: / 5.6.1998 / 19:03:32 / cg"
!
-startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream auxFrom:anAuxiliaryStream inDirectory:dir
+startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream
+ errorTo:anExternalErrStream auxFrom:anAuxiliaryStream
+ environment:anEvironmentDictionary inDirectory:dir
+
"start executing the OS command as specified by the argument, aCommandString
as a separate process; do not wait for the command to finish.
The commandString is passed to a shell for execution - see the description of
@@ -3806,7 +3811,7 @@
rslt := self
exec:(shellAndArgs at:1)
withArguments:(shellAndArgs at:2)
- environment:nil
+ environment:anEvironmentDictionary
fileDescriptors:(Array with:in fileDescriptor
with:out fileDescriptor
with:err fileDescriptor
@@ -3853,6 +3858,14 @@
"Modified: / 15.7.1997 / 16:03:51 / stefan"
"Modified: / 5.6.1998 / 19:03:51 / cg"
"Created: / 12.11.1998 / 14:39:20 / cg"
+!
+
+startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream
+ errorTo:anExternalErrStream auxFrom:anAuxiliaryStream inDirectory:dir
+
+ ^ self startProcess:aCommandString inputFrom:anExternalInStream
+ outputTo:anExternalOutStream errorTo:anExternalErrStream auxFrom:anAuxiliaryStream
+ environment:nil inDirectory:dir
! !
!UnixOperatingSystem class methodsFor:'file access'!
@@ -12731,7 +12744,7 @@
!UnixOperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.152 2003-04-01 10:36:44 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.153 2003-04-03 12:48:50 stefan Exp $'
! !
UnixOperatingSystem initialize!