Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #if defined(__FB_WIN32__)
- #Include Once "windows.bi"
- #elseif defined(__FB_LINUX__)
- #include once "crt/linux/unistd.bi"
- declare function ioctl alias "ioctl" (fd as integer, request as ulong, ...) as integer
- #define FIONREAD &h541B
- #endif
- Type BiPipe
- private:
- #if defined(__FB_WIN32__)
- hProcessHandle As HANDLE
- hWritePipe As HANDLE
- hReadPipe As HANDLE
- #elseif defined(__FB_LINUX__)
- pipeStdin as long
- pipeStdout as long
- #endif
- public:
- declare constructor (prgName as string)
- declare destructor ()
- declare function write (text as string) as integer
- declare function read (timeout as uinteger = 100) as string
- declare function readLine (separator As String = "a" & Chr(13,10), timeout as uinteger = 100) as string
- End Type
- #if defined(__FB_WIN32__)
- constructor BiPipe (prgName as string)
- Dim As STARTUPINFO si
- Dim As PROCESS_INFORMATION pi
- Dim As SECURITY_ATTRIBUTES sa
- Dim As HANDLE hReadPipe, hWritePipe, hReadChildPipe, hWriteChildPipe
- 'set security attributes
- sa.nLength = SizeOf(SECURITY_ATTRIBUTES)
- sa.lpSecurityDescriptor = NULL 'use default descriptor
- sa.bInheritHandle = TRUE
- 'create one pipe for each direction
- CreatePipe(@hReadChildPipe,@hWritePipe,@sa,0) 'parent to child
- CreatePipe(@hReadPipe,@hWriteChildPipe,@sa,0) 'child to parent
- GetStartupInfo(@si)
- si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
- si.wShowWindow = SW_HIDE 'appearance of child process window
- si.hStdOutput = hWriteChildPipe
- si.hStdError = hWriteChildPipe
- si.hStdInput = hReadChildPipe
- CreateProcess(0,PrgName,0,0,TRUE,CREATE_NEW_CONSOLE,0,0,@si,@pi)
- CloseHandle(hWriteChildPipe)
- CloseHandle(hReadChildPipe)
- this.hProcessHandle = pi.hProcess 'handle to child process
- this.hWritePipe = hWritePipe
- this.hReadPipe = hReadPipe
- end constructor
- destructor BiPipe ()
- TerminateProcess(hProcessHandle, 0)
- CloseHandle(hWritePipe)
- CloseHandle(hReadPipe)
- end destructor
- function BiPipe.write (text as string) as integer
- dim bytesWritten as integer
- WriteFile(hWritePipe, strptr(text), len(text), @bytesWritten, 0)
- return bytesWritten
- End Function
- function BiPipe.read (timeout as uinteger = 100) as string
- 'returns the whole pipe content until the pipe is empty or timeout occurs.
- ' timeout default is 100ms to prevent a deadlock
- Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage
- Dim As String buffer, retText
- Dim As Double tout = Timer + Cast(Double,timeout) / 1000
- Do
- PeekNamedPipe(hReadPipe,0,0,0,@iTotalBytesAvail,0)
- If iTotalBytesAvail Then
- buffer = String(iTotalBytesAvail,Chr(0))
- ReadFile(hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead,0)
- retText &= buffer
- ElseIf Len(retText) Then
- Exit Do
- EndIf
- Loop Until Timer > tout
- Return retText
- End Function
- function BiPipe.readLine (separator As String = "a" & Chr(13,10), timeout as uinteger = 100) as string
- 'returns the pipe content till the first separator if any, or otherwise the whole pipe
- ' content on timeout. timeout default is 100ms to prevent a deadlock
- Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage, endPtr
- Dim As String buffer, retText, mode
- Dim As Double tout = Timer + Cast(Double,timeout) / 1000
- mode = LCase(Left(separator,1))
- separator = Mid(separator,2)
- Do
- PeekNamedPipe(hReadPipe,0,0,0,@iTotalBytesAvail,0)
- If iTotalBytesAvail Then
- buffer = String(iTotalBytesAvail,Chr(0))
- PeekNamedPipe(hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead, _
- @iTotalBytesAvail,@iBytesLeftThisMessage) 'copy pipe content to buffer
- Select Case mode
- Case "a" 'any
- endPtr = InStr(buffer, Any separator) 'look for line end sign
- Case "e" 'exact
- endPtr = InStr(buffer, separator) 'look for line end sign
- End Select
- If endPtr Then 'return pipe content till line end
- Select Case mode
- Case "a"
- Do While (InStr(separator,Chr(buffer[endPtr - 1]))) And (endPtr < Len(buffer))
- endPtr += 1
- Loop
- endPtr -= 1
- Case "e"
- endPtr += Len(separator)
- End Select
- retText = Left(buffer,endPtr)
- ReadFile(hReadPipe,StrPtr(buffer),endPtr,@iNumberOfBytesRead,0) 'remove read bytes from pipe
- Select Case mode
- Case "a"
- Return RTrim(retText,Any separator) 'remove line end sign from returned string
- Case "e"
- Return Left(retText,Len(retText) - Len(separator))
- End Select
- EndIf
- EndIf
- Loop Until Timer > tout
- If iTotalBytesAvail Then 'return all pipe content
- buffer = String(iTotalBytesAvail,Chr(0))
- ReadFile(hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead,0)
- Return buffer
- EndIf
- Return ""
- End Function
- #elseif defined(__FB_LINUX__)
- constructor BiPipe (prgName as string)
- dim pipeStdin(0 to 1) as long
- dim pipeStdout(0 to 1) as long
- pipe_(@pipeStdin(0))
- pipe_(@pipeStdout(0))
- if fork() = 0 then
- close_(pipeStdin(1))
- close_(pipeStdout(0))
- dup2(pipeStdin(0), 0)
- dup2(pipeStdout(1), 1)
- execl(strptr("/bin/sh"), strptr("sh"), strptr("-c"), strptr(prgName), cast(ubyte ptr, 0))
- _exit(1)
- end if
- this.pipeStdin = pipeStdin(1)
- this.pipeStdout = pipeStdout(0)
- close_(pipeStdin(0))
- close_(pipeStdout(1))
- end constructor
- destructor BiPipe ()
- close_(pipeStdin)
- close_(pipeStdout)
- end destructor
- function BiPipe.write (text as string) as integer
- return write_(pipeStdin, strptr(text), len(text))
- End Function
- function BiPipe.read (timeout as uinteger = 100) as string
- 'returns the whole pipe content until the pipe is empty or timeout occurs.
- ' timeout default is 100ms to prevent a deadlock
- Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage
- Dim As String buffer, retText
- Dim As Double tout = Timer + Cast(Double,timeout) / 1000
- Do
- ioctl(pipeStdout, FIONREAD, @iTotalBytesAvail)
- If iTotalBytesAvail Then
- buffer = String(iTotalBytesAvail,Chr(0))
- read_(pipeStdout, strptr(buffer), len(buffer))
- retText &= buffer
- ElseIf Len(retText) Then
- Exit Do
- End If
- Loop Until Timer > tout
- Return retText
- End Function
- #if 0
- function BiPipe.readLine (separator As String = "a" & Chr(13,10), timeout as uinteger = 100) as string
- 'returns the pipe content till the first separator if any, or otherwise the whole pipe
- ' content on timeout. timeout default is 100ms to prevent a deadlock
- Dim As Integer iNumberOfBytesRead, iTotalBytesAvail, iBytesLeftThisMessage, endPtr
- Dim As String buffer, retText, mode
- Dim As Double tout = Timer + Cast(Double,timeout) / 1000
- mode = LCase(Left(separator,1))
- separator = Mid(separator,2)
- Do
- PeekNamedPipe(hReadPipe,0,0,0,@iTotalBytesAvail,0)
- If iTotalBytesAvail Then
- buffer = String(iTotalBytesAvail,Chr(0))
- PeekNamedPipe(hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead, _
- @iTotalBytesAvail,@iBytesLeftThisMessage) 'copy pipe content to buffer
- Select Case mode
- Case "a" 'any
- endPtr = InStr(buffer, Any separator) 'look for line end sign
- Case "e" 'exact
- endPtr = InStr(buffer, separator) 'look for line end sign
- End Select
- If endPtr Then 'return pipe content till line end
- Select Case mode
- Case "a"
- Do While (InStr(separator,Chr(buffer[endPtr - 1]))) And (endPtr < Len(buffer))
- endPtr += 1
- Loop
- endPtr -= 1
- Case "e"
- endPtr += Len(separator)
- End Select
- retText = Left(buffer,endPtr)
- ReadFile(hReadPipe,StrPtr(buffer),endPtr,@iNumberOfBytesRead,0) 'remove read bytes from pipe
- Select Case mode
- Case "a"
- Return RTrim(retText,Any separator) 'remove line end sign from returned string
- Case "e"
- Return Left(retText,Len(retText) - Len(separator))
- End Select
- EndIf
- EndIf
- Loop Until Timer > tout
- If iTotalBytesAvail Then 'return all pipe content
- buffer = String(iTotalBytesAvail,Chr(0))
- ReadFile(hReadPipe,StrPtr(buffer),Len(buffer),@iNumberOfBytesRead,0)
- Return buffer
- EndIf
- Return ""
- End Function
- #endif
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement