diff -r 000d1c4aa7e6 -r 324edacff5cc PipeStream.st --- a/PipeStream.st Tue May 17 00:56:14 2016 +0200 +++ b/PipeStream.st Tue May 17 02:04:25 2016 +0200 @@ -24,7 +24,7 @@ %{ #include "stxOSDefs.h" -#if defined(WIN32) +#if defined(__win32__) # undef UNIX_LIKE # define MSDOS_LIKE #endif @@ -165,28 +165,28 @@ For example, to get a stream reading the output of an 'ls -l' command, a PipeStream can be created with: - PipeStream readingFrom:'ls -l' + PipeStream readingFrom:'ls -l' the characters of the command's output can be read using the standard stream messages, such as next, nextLine etc. Example for writing to a command: - PipeStream writingTo:'cat >/tmp/x' + PipeStream writingTo:'cat >/tmp/x' Bidirectional pipestreams (supporting both reading an writing) may be used for filters: - PipeStream bidirectionalFor:'sed -e ''s/Hello/Greetings/''' + PipeStream bidirectionalFor:'sed -e ''s/Hello/Greetings/''' Buffered pipes do not work with Linux - the stdio library seems to be buggy (trying to restart the read ...) [author:] - Claus Gittinger + Claus Gittinger [see also:] - ExternalStream FileStream Socket - OperatingSystem + ExternalStream FileStream Socket + OperatingSystem " ! ! @@ -444,9 +444,9 @@ p isNil ifTrue:[^ nil]. [ - cmdOutput := p contentsAsString. + cmdOutput := p contentsAsString. ] ensure:[ - p close. + p close. ]. ^ cmdOutput @@ -491,9 +491,9 @@ "terminate first under windows" OperatingSystem isMSDOSlike ifTrue:[ - self terminatePipeCommand. - self closeFileDescriptor. - ^ self. + self terminatePipeCommand. + self closeFileDescriptor. + ^ self. ]. "terminate last under unix" @@ -568,7 +568,7 @@ if (@global(FileOpenTrace) == true) { console_fprintf(stderr, "close [PipeStream] %"_lx_" fd=%d\n", (INT)f, fileno(f)); } -#ifdef WIN32 +#ifdef __win32__ do { __threadErrno = 0; retVal = __STX_C_NOINT_CALL1( "close", (void*)close, (void*)fileno(f) ); @@ -611,17 +611,17 @@ realCmd execDirectory tmpComFile nullOutput resultPid errorNumber| handle notNil ifTrue:[ - "the pipe was already open ... - this should (can) not happen." - ^ self errorAlreadyOpen + "the pipe was already open ... + this should (can) not happen." + ^ self errorAlreadyOpen ]. rwMode = #r ifTrue:[ - mode := #readonly. didWrite := false. + mode := #readonly. didWrite := false. ] ifFalse:[rwMode = #'r+' ifTrue:[ - mode := #readwrite. didWrite := true. + mode := #readwrite. didWrite := true. ] ifFalse:[ - mode := #writeonly. didWrite := true. + mode := #writeonly. didWrite := true. ]]. lastErrorNumber := nil. @@ -633,79 +633,79 @@ execFdArray := #(0 1 2) copy. OperatingSystem isVMSlike ifTrue:[ - "/ - "/ the generated COM-file includes a 'set default' - "/ - tmpComFile := OperatingSystem createCOMFileForVMSCommand:aCommandString in:aDirectory. - realCmd := '@' , tmpComFile osName. - execDirectory := nil. + "/ + "/ the generated COM-file includes a 'set default' + "/ + tmpComFile := OperatingSystem createCOMFileForVMSCommand:aCommandString in:aDirectory. + realCmd := '@' , tmpComFile osName. + execDirectory := nil. - mbx := OperatingSystem createMailBox. - mbx isNil ifTrue:[ - lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. - tmpComFile delete. - ^ self openError:errorNumber. - ]. - mbxName := OperatingSystem mailBoxNameOf:mbx. + mbx := OperatingSystem createMailBox. + mbx isNil ifTrue:[ + lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. + tmpComFile delete. + ^ self openError:errorNumber. + ]. + mbxName := OperatingSystem mailBoxNameOf:mbx. - "/ 'mailBox is ' print. mbx print. ' name is ' print. mbxName printCR. - shellPath := ''. - shellArgs := realCmd. + "/ 'mailBox is ' print. mbx print. ' name is ' print. mbxName printCR. + shellPath := ''. + shellArgs := realCmd. - rwMode = #r ifTrue:[ - "redirect stdout of subprocess to write to mailbox" - execFdArray at:2 put:mbx. - ] ifFalse:[ - "redirect stdin of subprocess to read from mailbox" - execFdArray at:1 put:mbx. - ]. + rwMode = #r ifTrue:[ + "redirect stdout of subprocess to write to mailbox" + execFdArray at:2 put:mbx. + ] ifFalse:[ + "redirect stdin of subprocess to read from mailbox" + execFdArray at:1 put:mbx. + ]. ] ifFalse:[ - shellAndArgs := OperatingSystem commandAndArgsForOSCommand:realCmd. - shellPath := shellAndArgs at:1. - shellArgs := shellAndArgs at:2. + shellAndArgs := OperatingSystem commandAndArgsForOSCommand:realCmd. + shellPath := shellAndArgs at:1. + shellArgs := shellAndArgs at:2. - mode == #readwrite ifTrue:[ - pipeFdArray := OperatingSystem makeBidirectionalPipe. - pipeFdArray isNil ifTrue:[ - lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. - ^ self openError:errorNumber. - ]. - myFd := pipeFdArray at:1. - execFd := pipeFdArray at:2. - execFdArray at:1 put:execFd. - execFdArray at:2 put:execFd. - ] ifFalse:[ - pipeFdArray := OperatingSystem makePipe. - pipeFdArray isNil ifTrue:[ - lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. - ^ self openError:errorNumber. - ]. + mode == #readwrite ifTrue:[ + pipeFdArray := OperatingSystem makeBidirectionalPipe. + pipeFdArray isNil ifTrue:[ + lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. + ^ self openError:errorNumber. + ]. + myFd := pipeFdArray at:1. + execFd := pipeFdArray at:2. + execFdArray at:1 put:execFd. + execFdArray at:2 put:execFd. + ] ifFalse:[ + pipeFdArray := OperatingSystem makePipe. + pipeFdArray isNil ifTrue:[ + lastErrorNumber := errorNumber := OperatingSystem currentErrorNumber. + ^ self openError:errorNumber. + ]. - mode == #readonly ifTrue:[ - "redirect stdout of subprocess to write to pipe" - myFd := pipeFdArray at:1. - execFd := pipeFdArray at:2. - execFdArray at:2 put:execFd. - ] ifFalse:[ - "redirect stdin of subprocess to read from pipe" - myFd := pipeFdArray at:2. - execFd := pipeFdArray at:1. - execFdArray at:1 put:execFd. - ]. - ]. + mode == #readonly ifTrue:[ + "redirect stdout of subprocess to write to pipe" + myFd := pipeFdArray at:1. + execFd := pipeFdArray at:2. + execFdArray at:2 put:execFd. + ] ifFalse:[ + "redirect stdin of subprocess to read from pipe" + myFd := pipeFdArray at:2. + execFd := pipeFdArray at:1. + execFdArray at:1 put:execFd. + ]. + ]. ]. errorDisposition == #discard ifTrue:[ - nullOutput := Filename nullDevice writeStream. - execFdArray at:3 put:nullOutput fileDescriptor + nullOutput := Filename nullDevice writeStream. + execFdArray at:3 put:nullOutput fileDescriptor ] ifFalse:[ - (errorDisposition == #inline or:[errorDisposition == #stdout]) ifTrue:[ - execFdArray at:3 put:1 - ] ifFalse:[ + (errorDisposition == #inline or:[errorDisposition == #stdout]) ifTrue:[ + execFdArray at:3 put:1 + ] ifFalse:[ "/ errorDisposition isStream ifTrue:[ "/self halt. "/ ]. - ]. + ]. ]. "/ must block here, to avoid races due to early finishing @@ -715,84 +715,84 @@ "beware: pid may change if subprocess is fast" pid := resultPid := Processor - monitor:[ - OperatingSystem - exec:shellPath - withArguments:shellArgs - environment:nil - fileDescriptors:execFdArray - fork:true - newPgrp:true - inDirectory:execDirectory. - ] - action:[:status | - status stillAlive ifFalse:[ - exitStatus := status. + monitor:[ + OperatingSystem + exec:shellPath + withArguments:shellArgs + environment:nil + fileDescriptors:execFdArray + fork:true + newPgrp:true + inDirectory:execDirectory. + ] + action:[:status | + status stillAlive ifFalse:[ + exitStatus := status. - "writing doesn't make sense - there is no reader any longer" - mode == #readwrite ifTrue:[ - "... but allow to read the rest of the command's output" - self shutDownOutput. - ] ifFalse:[mode == #writeonly ifTrue:[ - self closeFileDescriptor. - ]]. + "writing doesn't make sense - there is no reader any longer" + mode == #readwrite ifTrue:[ + "... but allow to read the rest of the command's output" + self shutDownOutput. + ] ifFalse:[mode == #writeonly ifTrue:[ + self closeFileDescriptor. + ]]. - OperatingSystem closePid:pid. - pid := nil. - exitSema signal. - ]. - ]. + OperatingSystem closePid:pid. + pid := nil. + exitSema signal. + ]. + ]. "subprocess has been created. close unused filedescriptors" execFd notNil ifTrue:[ - OperatingSystem closeFd:execFd. + OperatingSystem closeFd:execFd. ]. nullOutput notNil ifTrue:[ - nullOutput close + nullOutput close ]. resultPid notNil ifTrue:[ - "successfull creation of subprocesss" - OperatingSystem isVMSlike ifTrue:[ - "/ - "/ reopen the mailbox as a file ... - "/ - mbxName := OperatingSystem mailBoxNameOf:mbx. - mbxName notNil ifTrue:[ - super open:mbxName withMode:rwMode. - exitAction := [tmpComFile delete]. - ]. - ] ifFalse:[ - self setFileDescriptor:myFd mode:rwMode. - handleType := #pipeFilePointer. - ] + "successfull creation of subprocesss" + OperatingSystem isVMSlike ifTrue:[ + "/ + "/ reopen the mailbox as a file ... + "/ + mbxName := OperatingSystem mailBoxNameOf:mbx. + mbxName notNil ifTrue:[ + super open:mbxName withMode:rwMode. + exitAction := [tmpComFile delete]. + ]. + ] ifFalse:[ + self setFileDescriptor:myFd mode:rwMode. + handleType := #pipeFilePointer. + ] ] ifFalse:[ - "creation of subprocesss failed" - lastErrorNumber := OperatingSystem currentErrorNumber. - OperatingSystem isVMSlike ifTrue:[ - OperatingSystem destroyMailBox:mbx. - tmpComFile delete. - ] ifFalse:[ - OperatingSystem closeFd:myFd. - ]. + "creation of subprocesss failed" + lastErrorNumber := OperatingSystem currentErrorNumber. + OperatingSystem isVMSlike ifTrue:[ + OperatingSystem destroyMailBox:mbx. + tmpComFile delete. + ] ifFalse:[ + OperatingSystem closeFd:myFd. + ]. ]. blocked ifFalse:[ - OperatingSystem unblockInterrupts + OperatingSystem unblockInterrupts ]. (resultPid isNil or:[lastErrorNumber notNil]) ifTrue:[ - " - the pipe open failed for some reason ... - ... this may be either due to an invalid command string, - or due to the system running out of memory (when forking - the unix process) - " - exitAction value. - ^ self openError:lastErrorNumber. + " + the pipe open failed for some reason ... + ... this may be either due to an invalid command string, + or due to the system running out of memory (when forking + the unix process) + " + exitAction value. + ^ self openError:lastErrorNumber. ]. commandString := realCmd.