{-# OPTIONS -ffi #-} module Shell( launch ) where import Foreign (Ptr, newArray0, nullPtr) import Foreign.C.String import GHC.Handle(openFd) -- is this also possible with System.Posix.IO ? import System.Posix.Internals import System.IO data Tuple_2_int = Tuple_2_int () foreign import ccall get_i1 :: (Ptr Tuple_2_int) -> IO(Int) foreign import ccall get_i2 :: (Ptr Tuple_2_int) -> IO(Int) foreign import ccall get_i3 :: (Ptr Tuple_2_int) -> IO(Int) foreign import ccall delete_tuple_2_int :: (Ptr Tuple_2_int) -> IO() foreign import ccall "launch" launchC :: CString -> (Ptr CString) -> IO (Ptr Tuple_2_int) open :: Int -> Maybe FDType -> IOMode -> IO Handle open fd mfdType mode = #if __GLASGOW_HASKELL__ < 604 openFd (fromIntegral fd) mfdType "test" mode True False #else openFd (fromIntegral fd) mfdType True "test" mode False #endif -- | Interactive IN/OUT/ERR launch of an application. launch :: String {- ^ shell command name -} -> [String] {- ^ raw arguments -} -> IO (Handle, Handle, Handle) {- ^ streams for input, output, error -} launch _ [] = error "Shell.pipe needs at least one element in argv." launch pName pArgs = do programname <- newCString pName arguments <- mapM newCString pArgs args <- newArray0 nullPtr arguments --The 0 is for the terminator tuple <- launchC programname args inputN <- get_i1 tuple outputN <- get_i2 tuple errorN <- get_i3 tuple delete_tuple_2_int tuple inputH <- open inputN (Nothing) WriteMode outputH <- open outputN (Just RegularFile) ReadMode errorH <- open errorN (Just RegularFile) ReadMode return (inputH,outputH,errorH)