# HG changeset patch # User Claus Gittinger # Date 910796986 -3600 # Node ID 028ca7c70ac93672a4e77803541c4466fc594720 # Parent 4cc33691696abd2299436e76729a82218590faa9 cleaned up the executeCommand protocol. diff -r 4cc33691696a -r 028ca7c70ac9 AbstractOperatingSystem.st --- a/AbstractOperatingSystem.st Wed Nov 11 16:02:35 1998 +0100 +++ b/AbstractOperatingSystem.st Wed Nov 11 16:09:46 1998 +0100 @@ -718,7 +718,17 @@ 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 fork:false + self exec:aCommandPath + withArguments:argArray + fileDescriptors:nil + closeDescriptors:nil + fork:false + newPgrp:false + inDirectory:nil + + "/ never reached ... + + "Modified: / 10.11.1998 / 20:57:02 / cg" ! exec:aCommandPath withArguments:argArray fork:doFork @@ -728,23 +738,24 @@ (typically, the xterm window)" ^ self exec:aCommandPath - withArguments:argArray - fileDescriptors:nil - closeDescriptors:nil - fork:doFork - newPgrp:false + withArguments:argArray + fileDescriptors:nil + closeDescriptors:nil + 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'. + 'I am the child'. + OperatingSystem + exec:'/bin/ls' + withArguments:#('ls' '/tmp') + fork:false. + 'not reached'. ] " @@ -753,12 +764,12 @@ 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'. + '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. @@ -767,7 +778,8 @@ OperatingSystem sendSignal:(OperatingSystem sigKILL) to:id " - "Modified: 15.7.1997 / 15:54:32 / stefan" + "Modified: / 15.7.1997 / 15:54:32 / stefan" + "Modified: / 10.11.1998 / 20:44:59 / cg" ! exec:aCommandPath withArguments:argArray fork:doFork inDirectory:aDirectory @@ -836,8 +848,12 @@ Return true if successful, false otherwise." ^ self - executeCommand:aCommandString - onError:[:status| false] + executeCommand:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + inDirectory:nil + onError:[:status| false] "unix: @@ -861,55 +877,33 @@ OperatingSystem executeCommand:'cc foo.c' " - "Modified: 7.1.1997 / 19:29:55 / stefan" - "Modified: 2.5.1997 / 12:27:39 / cg" + "Modified: / 7.1.1997 / 19:29:55 / stefan" + "Modified: / 10.11.1998 / 20:55:37 / cg" ! -executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream 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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[ - self - startProcess:aCommandString - inputFrom:anExternalInStream - outputTo:anExternalOutStream - errorTo:anExternalErrStream. - ] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := self osProcessStatusClass processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - "Modified: / 25.3.1997 / 11:02:02 / stefan" - "Modified: / 28.1.1998 / 14:46:36 / md" - "Created: / 5.6.1998 / 19:01:57 / cg" - "Modified: / 12.6.1998 / 16:30:08 / cg" +executeCommand:aCommandString inDirectory:aDirectory + "much like #executeCommand:, but changes the current directory + for the command. Since this is OS specific, use this instead of + hardwiring any 'cd ..' command strings into your applictions." + + ^ self + executeCommand:aCommandString + onError:[:status| false] + inDirectory:aDirectory + + " + OperatingSystem executeCommand:'tdump date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. + OperatingSystem executeCommand:'xxdir date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. + OperatingSystem executeCommand:'dir' inDirectory:'c:\'. + OperatingSystem executeCommand:'dir' + " + + "Modified: / 20.1.1998 / 17:03:03 / md" + "Modified: / 10.11.1998 / 20:28:10 / cg" + "Created: / 10.11.1998 / 21:05:45 / cg" ! -executeCommand:aCommandString onError:aBlock +executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream inDirectory:dirOrNil 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. @@ -922,38 +916,122 @@ sema := Semaphore new name:'OS command wait'. pid := Processor - monitor:[self startProcess:aCommandString] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. + monitor:[ + self + startProcess:aCommandString + inputFrom:anExternalInStream + outputTo:anExternalOutStream + errorTo:anExternalErrStream + inDirectory:dirOrNil. + ] + action:[:status | + status stillAlive ifFalse:[ + exitStatus := status. + self closePid:pid. + sema signal + ]. + ]. pid notNil ifTrue:[ - sema wait. + sema wait. ] ifFalse:[ - exitStatus := self osProcessStatusClass processCreationFailure. + exitStatus := self osProcessStatusClass processCreationFailure. ]. exitStatus success ifFalse:[ - ^ aBlock value:exitStatus + ^ aBlock value:exitStatus ]. ^ true. + " + OperatingSystem + executeCommand:'dir' + inputFrom:nil + outputTo:nil + errorTo:nil + onError:[:status | Transcript flash] + + OperatingSystem + executeCommand:'foo' + inputFrom:nil + outputTo:nil + errorTo:nil + onError:[:status | Transcript flash] + " + + "Modified: / 25.3.1997 / 11:02:02 / stefan" + "Modified: / 28.1.1998 / 14:46:36 / md" + "Modified: / 10.11.1998 / 20:48:08 / cg" + "Created: / 10.11.1998 / 20:51:11 / cg" +! + +executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream 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. + If not successfull, aBlock is called with an OsProcessStatus + (containing the exit status) as argument." + + ^ self + executeCommand:aCommandString + inputFrom:anExternalInStream + outputTo:anExternalOutStream + errorTo:anExternalErrStream + inDirectory:nil + onError:aBlock " - UnixOperatingSystem executeCommand:'sleep 30' onError:[]. - UnixOperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - UnixOperatingSystem executeCommand:'ls -l' onError:[]. - UnixOperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - UnixOperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. + OperatingSystem + executeCommand:'dir' + inputFrom:nil + outputTo:nil + errorTo:nil + onError:[:status | Transcript flash] + + OperatingSystem + executeCommand:'foo' + inputFrom:nil + outputTo:nil + errorTo:nil + onError:[:status | Transcript flash] + " + + "Modified: / 10.11.1998 / 20:51:39 / cg" +! + +executeCommand:aCommandString 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. + If not successfull, aBlock is called with an OsProcessStatus + (containing the exit status) as argument." + + ^ self + executeCommand:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + inDirectory:nil + onError:aBlock + + "unix: + + OperatingSystem executeCommand:'sleep 30' onError:[]. + OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. + OperatingSystem executeCommand:'ls -l' onError:[]. + OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. + OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. + + OperatingSystem executeCommand:'dir' onError:[]. + OperatingSystem executeCommand:'foo' onError:[]. + " "Modified: / 25.3.1997 / 11:06:43 / stefan" "Modified: / 28.1.1998 / 14:46:56 / md" "Created: / 5.6.1998 / 19:02:09 / cg" - "Modified: / 12.6.1998 / 16:30:12 / cg" + "Modified: / 10.11.1998 / 20:55:02 / cg" ! executeCommand:aCommandString onError:aBlock inDirectory:aDirectory @@ -964,41 +1042,15 @@ If not successfull, aBlock is called with an OsProcessStatus (containing the exit status) as argument." - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[self startProcess:aCommandString inDirectory:aDirectory] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := self osProcessStatusClass processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - - " - UnixOperatingSystem executeCommand:'sleep 30' onError:[]. - UnixOperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - UnixOperatingSystem executeCommand:'ls -l' onError:[]. - UnixOperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - UnixOperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. - " - - "Created: / 5.6.1998 / 19:02:22 / cg" - "Modified: / 12.6.1998 / 16:30:14 / cg" + ^ self + executeCommand:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + inDirectory:aDirectory + onError:aBlock + + "Modified: / 10.11.1998 / 20:54:37 / cg" ! fork @@ -1104,13 +1156,12 @@ Use #waitForProcess: for synchronization and exec status return, or #killProcess: to stop it." - |shellAndArgs| - - shellAndArgs := self commandAndArgsForOSCommand:aCommandString. ^ self - exec:(shellAndArgs at:1) - withArguments:(shellAndArgs at:2) - fork:true. + startProcess:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + inDirectory:nil " |pid| @@ -1119,9 +1170,28 @@ (Delay forSeconds:3) wait. OperatingSystem killProcess:pid. " - - "Modified: 21.3.1997 / 10:04:35 / dq" - "Modified: 2.5.1997 / 11:55:44 / cg" + " + |pid| + + pid := OperatingSystem startProcess:'dir/l'. + (Delay forSeconds:1) wait. + OperatingSystem killProcess:pid. + " + " + |pid| + + pid := OperatingSystem + startProcess:'dir/l' + inputFrom:nil + outputTo:Stdout + errorTo:nil + inDirectory:nil. + (Delay forSeconds:2) wait. + OperatingSystem killProcess:pid. + " + + "Modified: / 21.3.1997 / 10:04:35 / dq" + "Modified: / 10.11.1998 / 21:03:50 / cg" ! startProcess:aCommandString inDirectory:aDirectory @@ -1133,14 +1203,12 @@ Use #waitForProcess: for synchronization and exec status return, or #killProcess: to stop it." - |shellAndArgs| - - shellAndArgs := self commandAndArgsForOSCommand:aCommandString. ^ self - exec:(shellAndArgs at:1) - withArguments:(shellAndArgs at:2) - fork:true - inDirectory:aDirectory. + startProcess:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + inDirectory:aDirectory " |pid| @@ -1149,9 +1217,9 @@ OperatingSystem killProcess:pid. " - "Modified: 21.3.1997 / 10:04:35 / dq" - "Modified: 2.5.1997 / 11:55:44 / cg" - "Modified: 28.1.1998 / 14:13:33 / md" + "Modified: / 21.3.1997 / 10:04:35 / dq" + "Modified: / 28.1.1998 / 14:13:33 / md" + "Modified: / 10.11.1998 / 20:59:33 / cg" ! startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream @@ -1165,7 +1233,30 @@ Use #monitorPid:action: for synchronization and exec status return, or #killProcess: to stop it." + ^ self + startProcess:aCommandString + inputFrom:anExternalInStream + outputTo:anExternalOutStream + errorTo:anExternalErrStream + inDirectory:nil + + "Modified: / 10.11.1998 / 20:59:05 / cg" +! + +startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream 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 + 'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual). + The command gets stdIn, stdOut and stdErr assigned from the arguments; + each may be nil. + Return the processId if successful, nil otherwise. + Use #monitorPid:action: for synchronization and exec status return, + or #killProcess: to stop it." + self subclassResponsibility + + "Created: / 10.11.1998 / 20:58:00 / cg" ! ! !AbstractOperatingSystem class methodsFor:'file access'! @@ -3359,6 +3450,6 @@ !AbstractOperatingSystem class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.9 1998-10-29 12:20:54 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/AbstractOperatingSystem.st,v 1.10 1998-11-11 15:09:46 cg Exp $' ! ! AbstractOperatingSystem initialize! diff -r 4cc33691696a -r 028ca7c70ac9 Win32OS.st --- a/Win32OS.st Wed Nov 11 16:02:35 1998 +0100 +++ b/Win32OS.st Wed Nov 11 16:09:46 1998 +0100 @@ -2396,227 +2396,58 @@ "Modified: / 11.9.1998 / 19:03:55 / cg" ! -exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp - "Internal lowLevel entry for combined fork & exec; +exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory + "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 process id of the child process is returned; nil if the fork failed. + fork a child to do the above. + The process id 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 - on VMS, these must be channels as returned by createMailBox. + 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 + on VMS, these must be channels as returned by createMailBox. closeFdArray contains descriptors that will be closed in the subprocess. - closeDescriptors are ignored in the WIN32 & VMS versions. + closeDescriptors are ignored in the WIN32 & VMS versions. 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. - - Notice: this used to be two separate ST-methods; however, in order to use - vfork on some machines, it had to be merged into one, to avoid write - accesses to ST/X memory from the vforked-child. - The code below only does read accesses." - - ^ self - exec:aCommandPath - withArguments:argArray - fileDescriptors:fdArray - closeDescriptors:closeFdArray - fork:doFork - newPgrp:newPgrp - inDirectory:nil. -! - -exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory - "Internal lowLevel entry for combined fork & exec for WIN32" + The processgroup will be equal to id. + newPgrp is not used on WIN32 and VMS systems." |path| - aDirectory isNil ifTrue:[ - path := nil. - ] ifFalse:[ - path := aDirectory asFilename pathName asFilename osNameForDirectory. - (path endsWith:':') ifTrue:[ - path := path , '\'. - ]. - ]. - ^ self - primExec:aCommandPath - withArguments:argArray - fileDescriptors:fdArray - closeDescriptors:closeFdArray - fork:doFork - newPgrp:newPgrp - inPath:path - - "Modified: 31.1.1998 / 10:54:24 / md" -! - -executeCommand:aCommandString inDirectory:aDirectory - "much like #executeCommand:, but changes the current directory - for the command. Since this is OS specific, use this instead of - hardwiring any 'cd ..' command strings into your applictions." - - ^ self - executeCommand:aCommandString - onError:[:status| false] - inDirectory:aDirectory - - " - OperatingSystem executeCommand:'tdump date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. - OperatingSystem executeCommand:'xxdir date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. - " - - "Modified: / 20.1.1998 / 17:03:03 / md" - "Modified: / 11.9.1998 / 18:52:36 / cg" -! - -executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream 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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'Unix command wait'. - - pid := Processor - monitor:[ - self - startProcess:aCommandString - inputFrom:anExternalInStream - outputTo:anExternalOutStream - errorTo:anExternalErrStream. - ] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus + + aDirectory notNil ifTrue:[ + path := aDirectory asFilename asAbsoluteFilename osNameForDirectory. + (path endsWith:':') ifTrue:[ + path := path , '\'. + ]. ]. - ^ true. - - "Modified: 25.3.1997 / 11:02:02 / stefan" - "Modified: 19.4.1997 / 18:15:04 / cg" - "Modified: 28.1.1998 / 14:46:36 / md" -! - -executeCommand:aCommandString 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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[self startProcess:aCommandString] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - - " - OperatingSystem executeCommand:'sleep 30' onError:[]. - OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - OperatingSystem executeCommand:'ls -l' onError:[]. - OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. - " - - "Created: 22.12.1995 / 14:49:59 / stefan" - "Modified: 25.3.1997 / 11:06:43 / stefan" - "Modified: 19.4.1997 / 18:14:41 / cg" - "Modified: 28.1.1998 / 14:46:56 / md" -! - -executeCommand:aCommandString onError:aBlock inDirectory:aDirectory - "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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[self startProcess:aCommandString inDirectory:aDirectory] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - - " - OperatingSystem executeCommand:'sleep 30' onError:[]. - OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - OperatingSystem executeCommand:'ls -l' onError:[]. - OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. - " - - "Created: 28.1.1998 / 14:12:15 / md" + + ^ self + primExec:aCommandPath + withArguments:argArray + fileDescriptors:fdArray + closeDescriptors:closeFdArray + fork:doFork + newPgrp:newPgrp + inPath:path + + "Modified: / 31.1.1998 / 10:54:24 / md" + "Modified: / 10.11.1998 / 20:44:24 / cg" ! getStatusOfProcess:aProcessId @@ -2870,7 +2701,7 @@ ^ self primitiveFailed ! -startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream +startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream inDirectory:dirOrNil "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 @@ -2884,56 +2715,27 @@ |in out err shellAndArgs| anExternalInStream notNil ifTrue:[ - in := anExternalInStream fileDescriptor. + in := anExternalInStream fileDescriptor. ]. anExternalOutStream notNil ifTrue:[ - out := anExternalOutStream fileDescriptor. + out := anExternalOutStream fileDescriptor. ]. anExternalErrStream notNil ifTrue:[ - err := anExternalErrStream fileDescriptor. + err := anExternalErrStream fileDescriptor. ]. shellAndArgs := self commandAndArgsForOSCommand:aCommandString. ^ self - exec:(shellAndArgs at:1) - withArguments:(shellAndArgs at:2) - fileDescriptors:(Array with:in with:out with:err) - closeDescriptors:nil - fork:true - newPgrp:false. - - "blocking at current prio (i.e. only higher prio threads execute): - - OperatingSystem executeCommand:'dir'. - " - - "non-blocking (lower prio threads continue): - - |in out err pid sema| - - in := 'out' asFilename readStream. - out := 'out2' asFilename writeStream. - err := 'err' asFilename writeStream. - - sema := Semaphore new. - pid := OperatingSystem startProcess:'grep drw' inputFrom:in outputTo:out errorTo:err. - - The following will no longer work. monitorPid has disappeared - - pid notNil ifTrue:[ - Processor monitorPid:pid action:[:OSstatus | sema signal ]. - ]. - in close. - out close. - err close. - sema wait. - Transcript showCR:'finished' - " - - "Created: 29.2.1996 / 12:31:29 / cg" - "Modified: 21.3.1997 / 10:04:35 / dq" - "Modified: 2.5.1997 / 12:18:20 / cg" - "Modified: 15.7.1997 / 16:03:51 / stefan" + exec:(shellAndArgs at:1) + withArguments:(shellAndArgs at:2) + fileDescriptors:(Array with:in with:out with:err) + closeDescriptors:nil + fork:true + newPgrp:false + inDirectory:dirOrNil + + "Modified: / 10.11.1998 / 20:43:12 / cg" + "Created: / 10.11.1998 / 20:48:35 / cg" ! ! !Win32OperatingSystem class methodsFor:'file access'! @@ -6851,6 +6653,6 @@ !Win32OperatingSystem class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/Attic/Win32OS.st,v 1.34 1998-10-29 12:27:26 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/Attic/Win32OS.st,v 1.35 1998-11-11 15:09:11 cg Exp $' ! ! Win32OperatingSystem initialize! diff -r 4cc33691696a -r 028ca7c70ac9 Win32OperatingSystem.st --- a/Win32OperatingSystem.st Wed Nov 11 16:02:35 1998 +0100 +++ b/Win32OperatingSystem.st Wed Nov 11 16:09:46 1998 +0100 @@ -2396,227 +2396,58 @@ "Modified: / 11.9.1998 / 19:03:55 / cg" ! -exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp - "Internal lowLevel entry for combined fork & exec; +exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory + "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 process id of the child process is returned; nil if the fork failed. + fork a child to do the above. + The process id 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 - on VMS, these must be channels as returned by createMailBox. + 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 + on VMS, these must be channels as returned by createMailBox. closeFdArray contains descriptors that will be closed in the subprocess. - closeDescriptors are ignored in the WIN32 & VMS versions. + closeDescriptors are ignored in the WIN32 & VMS versions. 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. - - Notice: this used to be two separate ST-methods; however, in order to use - vfork on some machines, it had to be merged into one, to avoid write - accesses to ST/X memory from the vforked-child. - The code below only does read accesses." - - ^ self - exec:aCommandPath - withArguments:argArray - fileDescriptors:fdArray - closeDescriptors:closeFdArray - fork:doFork - newPgrp:newPgrp - inDirectory:nil. -! - -exec:aCommandPath withArguments:argArray fileDescriptors:fdArray closeDescriptors:closeFdArray fork:doFork newPgrp:newPgrp inDirectory:aDirectory - "Internal lowLevel entry for combined fork & exec for WIN32" + The processgroup will be equal to id. + newPgrp is not used on WIN32 and VMS systems." |path| - aDirectory isNil ifTrue:[ - path := nil. - ] ifFalse:[ - path := aDirectory asFilename pathName asFilename osNameForDirectory. - (path endsWith:':') ifTrue:[ - path := path , '\'. - ]. - ]. - ^ self - primExec:aCommandPath - withArguments:argArray - fileDescriptors:fdArray - closeDescriptors:closeFdArray - fork:doFork - newPgrp:newPgrp - inPath:path - - "Modified: 31.1.1998 / 10:54:24 / md" -! - -executeCommand:aCommandString inDirectory:aDirectory - "much like #executeCommand:, but changes the current directory - for the command. Since this is OS specific, use this instead of - hardwiring any 'cd ..' command strings into your applictions." - - ^ self - executeCommand:aCommandString - onError:[:status| false] - inDirectory:aDirectory - - " - OperatingSystem executeCommand:'tdump date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. - OperatingSystem executeCommand:'xxdir date.obj' inDirectory:'c:\winstx\stx\libbasic\objbc'. - " - - "Modified: / 20.1.1998 / 17:03:03 / md" - "Modified: / 11.9.1998 / 18:52:36 / cg" -! - -executeCommand:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream 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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'Unix command wait'. - - pid := Processor - monitor:[ - self - startProcess:aCommandString - inputFrom:anExternalInStream - outputTo:anExternalOutStream - errorTo:anExternalErrStream. - ] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus + + aDirectory notNil ifTrue:[ + path := aDirectory asFilename asAbsoluteFilename osNameForDirectory. + (path endsWith:':') ifTrue:[ + path := path , '\'. + ]. ]. - ^ true. - - "Modified: 25.3.1997 / 11:02:02 / stefan" - "Modified: 19.4.1997 / 18:15:04 / cg" - "Modified: 28.1.1998 / 14:46:36 / md" -! - -executeCommand:aCommandString 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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[self startProcess:aCommandString] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - - " - OperatingSystem executeCommand:'sleep 30' onError:[]. - OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - OperatingSystem executeCommand:'ls -l' onError:[]. - OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. - " - - "Created: 22.12.1995 / 14:49:59 / stefan" - "Modified: 25.3.1997 / 11:06:43 / stefan" - "Modified: 19.4.1997 / 18:14:41 / cg" - "Modified: 28.1.1998 / 14:46:56 / md" -! - -executeCommand:aCommandString onError:aBlock inDirectory:aDirectory - "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. - If not successfull, aBlock is called with an OsProcessStatus - (containing the exit status) as argument." - - |pid exitStatus sema| - - sema := Semaphore new name:'OS command wait'. - - pid := Processor - monitor:[self startProcess:aCommandString inDirectory:aDirectory] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. - self closePid:pid. - sema signal - ]. - ]. - pid notNil ifTrue:[ - sema wait. - ] ifFalse:[ - exitStatus := OSProcessStatus processCreationFailure. - ]. - - exitStatus success ifFalse:[ - ^ aBlock value:exitStatus - ]. - ^ true. - - - " - OperatingSystem executeCommand:'sleep 30' onError:[]. - OperatingSystem executeCommand:'pwd' onError:[:status|status inspect]. - OperatingSystem executeCommand:'ls -l' onError:[]. - OperatingSystem executeCommand:'invalidCommand' onError:[:status| status inspect]. - OperatingSystem executeCommand:'rm /tmp/foofoofoofoo'onError:[:status | status inspect]. - " - - "Created: 28.1.1998 / 14:12:15 / md" + + ^ self + primExec:aCommandPath + withArguments:argArray + fileDescriptors:fdArray + closeDescriptors:closeFdArray + fork:doFork + newPgrp:newPgrp + inPath:path + + "Modified: / 31.1.1998 / 10:54:24 / md" + "Modified: / 10.11.1998 / 20:44:24 / cg" ! getStatusOfProcess:aProcessId @@ -2870,7 +2701,7 @@ ^ self primitiveFailed ! -startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream +startProcess:aCommandString inputFrom:anExternalInStream outputTo:anExternalOutStream errorTo:anExternalErrStream inDirectory:dirOrNil "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 @@ -2884,56 +2715,27 @@ |in out err shellAndArgs| anExternalInStream notNil ifTrue:[ - in := anExternalInStream fileDescriptor. + in := anExternalInStream fileDescriptor. ]. anExternalOutStream notNil ifTrue:[ - out := anExternalOutStream fileDescriptor. + out := anExternalOutStream fileDescriptor. ]. anExternalErrStream notNil ifTrue:[ - err := anExternalErrStream fileDescriptor. + err := anExternalErrStream fileDescriptor. ]. shellAndArgs := self commandAndArgsForOSCommand:aCommandString. ^ self - exec:(shellAndArgs at:1) - withArguments:(shellAndArgs at:2) - fileDescriptors:(Array with:in with:out with:err) - closeDescriptors:nil - fork:true - newPgrp:false. - - "blocking at current prio (i.e. only higher prio threads execute): - - OperatingSystem executeCommand:'dir'. - " - - "non-blocking (lower prio threads continue): - - |in out err pid sema| - - in := 'out' asFilename readStream. - out := 'out2' asFilename writeStream. - err := 'err' asFilename writeStream. - - sema := Semaphore new. - pid := OperatingSystem startProcess:'grep drw' inputFrom:in outputTo:out errorTo:err. - - The following will no longer work. monitorPid has disappeared - - pid notNil ifTrue:[ - Processor monitorPid:pid action:[:OSstatus | sema signal ]. - ]. - in close. - out close. - err close. - sema wait. - Transcript showCR:'finished' - " - - "Created: 29.2.1996 / 12:31:29 / cg" - "Modified: 21.3.1997 / 10:04:35 / dq" - "Modified: 2.5.1997 / 12:18:20 / cg" - "Modified: 15.7.1997 / 16:03:51 / stefan" + exec:(shellAndArgs at:1) + withArguments:(shellAndArgs at:2) + fileDescriptors:(Array with:in with:out with:err) + closeDescriptors:nil + fork:true + newPgrp:false + inDirectory:dirOrNil + + "Modified: / 10.11.1998 / 20:43:12 / cg" + "Created: / 10.11.1998 / 20:48:35 / cg" ! ! !Win32OperatingSystem class methodsFor:'file access'! @@ -6851,6 +6653,6 @@ !Win32OperatingSystem class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.34 1998-10-29 12:27:26 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.35 1998-11-11 15:09:11 cg Exp $' ! ! Win32OperatingSystem initialize!