{-# 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)

