process-iterio (empty) → 0.0.0
raw patch · 5 files changed
+199/−0 lines, 5 filesdep +basedep +bytestringdep +cpphssetup-changed
Dependencies added: base, bytestring, cpphs, iterIO, process, transformers
Files
- Data/IterIO/Process.hs +110/−0
- LICENSE +30/−0
- Setup.hs +6/−0
- Test.hs +11/−0
- process-iterio.cabal +42/−0
+ Data/IterIO/Process.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE OverloadedStrings #-}++-- | A library for enumerating OS process input and output with IterIO's stream transformers.++module Data.IterIO.Process+ ( enumProcess+ , cmd+ ) where++import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy as L+import System.Process hiding (readProcess)+import System.IO(hClose, hFlush, Handle)+import System.Exit(ExitCode(ExitFailure))+import Control.Monad.IO.Class(liftIO, MonadIO)+import Data.IterIO+import Control.Exception(ErrorCall(ErrorCall))++-- | Create an Onum that starts and executable at the given FilePath,+-- passing it args, and routing the process's stdout to the Onum's+-- output stream. If the executable fails, an exception is +-- thrown with the contents of stderr.+enumProcess :: FilePath -> [String] -> Onum ByteString IO a+enumProcess p args = inumBracket (mkProc p args) cleanup procInum_++-- | Create an Inum that starts and executable at the given FilePath,+-- and passing it args. The Inum's input stream is routed to stdin,+-- and stdout goes to the Inum's output stream. If the executable+-- fails, an exception is thrown with the contents of stderr.+cmd :: MonadIO m => FilePath -> [String] -> Inum ByteString ByteString m a+cmd p args = inumBracket (mkProc p args) cleanup procInum+++-- Make the process object+mkProc :: MonadIO m => FilePath -> [String] -> m (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)+mkProc p args = liftIO $ do+ createProcess (proc p args){+ std_in = CreatePipe+ , std_out = CreatePipe+ , std_err = CreatePipe+ }++-- Cleanup routine for process inums+cleanup :: MonadIO m => (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> m ()+cleanup (Just i, Just o, Just e, _) = liftIO $ do+ hClose i+ hClose o+ hClose e+cleanup _ = error "the impossible happened"++-- Process Inum for an existing process+procInum :: (MonadIO m) => (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> Inum ByteString ByteString m a+procInum (Just i, Just o, Just e, pid) = mkInumM loop+ where+ loop = do+ -- Grab any data we have for stidin+ Chunk t eof <- chunkI+ liftIO $ L.hPut i t++ -- Close stdin if no more data. This will allow the process exit.+ if eof+ then liftIO $ hClose i+ else liftIO $ hFlush i++ done <- feedStdout i o e pid+ if done+ then return L.empty+ else loop+procInum _ = error "unsupported configuration"+++-- Process Onum for an existing process+procInum_ :: (MonadIO m) => (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> Onum ByteString m a+procInum_ (Just i, Just o, Just e, pid) = mkInumM loop+ where+ loop = do+ done <- feedStdout i o e pid+ if done+ then return L.empty+ else loop+procInum_ _ = error "unsupported configuration"+++-- TODO: InumState is not exposed by the Inum module. Is it possible to add a type signature here?+--feedStdout :: (MonadIO m, ChunkData t) => Handle -> Handle -> Handle -> ProcessHandle -> Iter t (IterStateT (InumState t ByteString m a) m) Bool+feedStdout i o e pid = do+ -- Close stdin if no more data. This will allow the process exit.+ liftIO $ hClose i++ -- After stdin exits, the exe will write to stdout and then close it.+ maybeExitCode <- liftIO $ getProcessExitCode pid++ case maybeExitCode of+ Just (ExitFailure _) -> do+ msg <- liftIO $ B.hGetContents e+ throwI (ErrorCall (B8.unpack msg))++ _ -> return ()++ -- Grab any data we have on stdout+ output <- liftIO $ L.hGetNonBlocking o 1024++ -- Push proc's stdout to the inum's output stream+ notListening <- ifeed output++ -- Debate our future+ return $ notListening || maybeExitCode /= Nothing
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright 2012 Greg Fitzgerald++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ Test.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE OverloadedStrings #-}++import Data.IterIO.Process(cmd, enumProcess)+import Data.IterIO(enumPure, (|.), (|$), stdoutI)++main :: IO ()+main = do+ enumProcess "ls" [] |. cmd "grep" ["cabal"] |$ stdoutI+ enumPure "very cool\n" |. cmd "cat" [] |$ stdoutI++
+ process-iterio.cabal view
@@ -0,0 +1,42 @@+Name: process-iterio+Version: 0.0.0+Synopsis: IterIO Process Library+Description: IterIO combinators for the Process library+Homepage: https://github.com/garious/process-iterio+License: BSD3+License-file: LICENSE+Author: Greg Fitzgerald <garious@gmail.com>+Maintainer: Greg Fitzgerald <garious@gmail.com>+Category: System+Build-type: Simple+Cabal-version: >=1.8++source-repository head+ Type: git+ Location: https://github.com/garious/process-iterio++Library+ ghc-options: -Wall++ Exposed-modules:+ Data.IterIO.Process++ Build-depends:+ base >= 4 && < 5,+ process,+ iterIO,+ transformers,+ bytestring,+ cpphs++Test-Suite Test+ type: exitcode-stdio-1.0+ main-is: Test.hs+ GHC-Options: -Wall -fno-ignore-asserts+ Build-depends:+ base,+ process,+ iterIO,+ transformers,+ bytestring,+ cpphs