UnixPTYStream.st
changeset 4245 79cce4a51ea1
parent 4242 f870cb692e7e
child 4254 7cccdc94fa82
child 4558 6b2a3c9cec9f
equal deleted inserted replaced
4244:66c023206027 4245:79cce4a51ea1
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1998 by eXept Software AG
     4  COPYRIGHT (c) 1998 by eXept Software AG
     3               All Rights Reserved
     5               All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   180 !UnixPTYStream methodsFor:'private'!
   182 !UnixPTYStream methodsFor:'private'!
   181 
   183 
   182 openPTYFor:aCommandString withMode:openMode inDirectory:aDirectory
   184 openPTYFor:aCommandString withMode:openMode inDirectory:aDirectory
   183     "open a pty to the unix command in commandString"
   185     "open a pty to the unix command in commandString"
   184 
   186 
   185     |blocked ptyFdArray execFdArray slaveFd masterFd shellAndArgs
   187     |ptyFdArray slaveFd masterFd env remotePipeEnd result|
   186      shellPath shellArgs mbx mbxName env|
       
   187 
   188 
   188     handle notNil ifTrue:[
   189     handle notNil ifTrue:[
   189         "the pipe was already open ...
   190         "the pipe was already open ...
   190          this should (can) not happen."
   191          this should (can) not happen."
   191         ^ self errorAlreadyOpen
   192         ^ self errorAlreadyOpen
   192     ].
   193     ].
   193         
   194         
   194     lastErrorNumber := nil.
   195     lastErrorNumber := nil.
   195     exitStatus := nil.
   196     "stdio lib does not work with blocking pipes and interrupts
   196     exitSema := Semaphore new name:'pty exitSema'.
   197      for WIN, Linux, Solaris and probably any other UNIX"
       
   198     buffered := false.
       
   199     hitEOF := false.
       
   200     binary := false.
   197     
   201     
   198     OperatingSystem isVMSlike ifTrue:[
   202     ptyFdArray := OperatingSystem makePTYPair.
   199         mbx := OperatingSystem createMailBox.
   203     ptyFdArray isNil ifTrue:[
   200         mbx isNil ifTrue:[
   204         lastErrorNumber := OperatingSystem lastErrorNumber.
   201             lastErrorNumber := OperatingSystem currentErrorNumber.
   205         ^ self openError:lastErrorNumber.
   202             ^ self openError
   206     ].
   203         ].
   207 
   204         mbxName := OperatingSystem mailBoxNameOf:mbx.
   208     masterFd := ptyFdArray at:1.
   205         "/ 'mailBox is ' print. mbx print. ' name is ' print. mbxName printCR.
   209     slaveFd := ptyFdArray at:2.
   206 
   210 
   207         shellPath := ''.
   211     remotePipeEnd := self class forFileDescriptor:slaveFd mode:#readwrite buffered:false handleType:#pipeFilePointer.
   208         shellArgs := aCommandString.
       
   209 
       
   210         execFdArray := Array with:mbx with:mbx with:mbx.
       
   211     ] ifFalse:[
       
   212         ptyFdArray := OperatingSystem makePTYPair.
       
   213         ptyFdArray isNil ifTrue:[
       
   214             lastErrorNumber := OperatingSystem currentErrorNumber.
       
   215             ^ self openError
       
   216         ].
       
   217 
       
   218         shellAndArgs := OperatingSystem commandAndArgsForOSCommand:aCommandString.
       
   219         shellPath := shellAndArgs at:1.
       
   220         shellArgs := shellAndArgs at:2.
       
   221 
       
   222         masterFd := ptyFdArray at:1.
       
   223         slaveFd := ptyFdArray at:2.
       
   224         execFdArray := Array with:slaveFd with:slaveFd with:slaveFd.
       
   225     ].
       
   226 
   212 
   227     env := Dictionary new.
   213     env := Dictionary new.
   228     env at:'TERM'  put:'dumb'.
   214     env at:'TERM'  put:'dumb'.
   229     env at:'SHELL' put:shellPath.
   215     env at:'SHELL' put:'/bin/sh'.
   230 
   216 
   231     "/ must block here, to avoid races due to early finishing
   217     osProcess := OSProcess new 
   232     "/ subprocesses ...
   218                     command:aCommandString;
   233 
   219                     directory:aDirectory;
   234     blocked := OperatingSystem blockInterrupts.
   220                     environment:env;
   235 
   221                     inStream:remotePipeEnd;
   236     pid := Processor 
   222                     outStream:remotePipeEnd;
   237                monitor:[
   223                     errorStream:remotePipeEnd.
   238                   OperatingSystem 
   224 
   239                       exec:shellPath
   225     result := osProcess startProcess.
   240                       withArguments:shellArgs
   226 
   241                       environment:env
   227     remotePipeEnd notNil ifTrue:[
   242                       fileDescriptors:execFdArray
   228         remotePipeEnd close.
   243                       fork:true
   229     ].
   244                       newPgrp:true
   230 
   245                       inDirectory:aDirectory
   231     result ifTrue:[
   246                       showWindow:nil.
   232         self setFileHandle:masterFd mode:openMode.
   247                ]
       
   248                action:[:status |
       
   249                   status stillAlive ifFalse:[
       
   250                       exitStatus := status.
       
   251                       OperatingSystem closePid:pid.
       
   252                       pid := nil.
       
   253                       exitSema signal.
       
   254                   ].
       
   255                ].
       
   256 
       
   257     (OperatingSystem isVMSlike) ifFalse:[
       
   258         OperatingSystem closeFd:slaveFd.
       
   259     ].
       
   260 
       
   261     pid notNil ifTrue:[
       
   262         (OperatingSystem isVMSlike) ifTrue:[
       
   263             "/
       
   264             "/ reopen the mailbox as a file ...
       
   265             "/
       
   266             mbxName := OperatingSystem mailBoxNameOf:mbx.
       
   267             mbxName notNil ifTrue:[
       
   268                 self open:mbxName withMode:openMode
       
   269             ].
       
   270         ] ifFalse:[
       
   271             self setFileHandle:masterFd mode:openMode.
       
   272         ]
       
   273     ] ifFalse:[
   233     ] ifFalse:[
   274         lastErrorNumber := OperatingSystem currentErrorNumber.
   234         "the pipe open failed for some reason ...
   275         OperatingSystem isVMSlike ifTrue:[
       
   276             OperatingSystem destroyMailBox:mbx
       
   277         ] ifFalse:[
       
   278             OperatingSystem closeFd:masterFd.
       
   279         ].
       
   280     ].
       
   281 
       
   282     blocked ifFalse:[
       
   283         OperatingSystem unblockInterrupts
       
   284     ].
       
   285 
       
   286     lastErrorNumber notNil ifTrue:[
       
   287         "
       
   288          the pipe open failed for some reason ...
       
   289          ... this may be either due to an invalid command string,
   235          ... this may be either due to an invalid command string,
   290          or due to the system running out of memory (when forking
   236          or due to the system running out of memory (when forking
   291          the unix process)
   237          the unix process)"
   292         "
   238         lastErrorNumber := OperatingSystem lastErrorNumber.
   293         ^ self openError
   239         OperatingSystem closeFd:masterFd.
   294     ].
   240         ^ self openError:lastErrorNumber.
   295 
   241     ].
   296     commandString := aCommandString.
   242 
   297     buffered := false.
   243     self registerForFinalization.
   298 
       
   299     hitEOF := false.
       
   300     binary := false.
       
   301     Lobby register:self.
       
   302 
   244 
   303     "Created: / 9.7.1998 / 20:21:42 / cg"
   245     "Created: / 9.7.1998 / 20:21:42 / cg"
   304     "Modified: / 9.7.1998 / 20:28:31 / cg"
   246     "Modified: / 9.7.1998 / 20:28:31 / cg"
   305 !
   247 !
   306 
   248