% Copyright (C) 2003 David Roundy % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2, or (at your option) % any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software Foundation, % Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \begin{code} module Exec ( exec ) where import System import IO import Foreign import Foreign.C import Foreign.Marshal.Array ( withArray0 ) import Monad ( liftM ) withCStrings :: [String] -> (Ptr CString -> IO a) -> IO a withCStrings strings doit = wcss strings [] where wcss [] css = withArray0 nullPtr (reverse css) $ \aack -> doit aack wcss (s:ss) css = withCString s $ \cstr -> wcss ss (cstr:css) exec :: String -> [String] -> FilePath -> FilePath -> IO ExitCode #ifdef HELLOWIN32 exec c args "/dev/null" "/dev/null" = system $ c++" "++careful_unwords args exec c args "/dev/null" out = system $ c++" "++careful_unwords args++" > "++out exec c args inp "/dev/null" = system $ c++" "++careful_unwords args++" < "++inp exec c args inp out = system $ c++" "++careful_unwords args++" < "++inp++" > "++out careful_unwords (a:as) = "\""++a++"\" "++ careful_unwords as careful_unwords [] = "" #else exec c args inp out = do fval <- c_fork case fval of -1 -> return $ ExitFailure $ 1 0 -> withCString inp $ \in_c -> withCString out $ \out_c -> withCString c $ \c_c -> withCStrings (c:args) $ \c_args -> do fdin <- open_read in_c fdout <- open_write out_c c_dup2 fdout 1 c_dup2 fdout 2 c_dup2 fdin 0 -- execvp only returns if there is an error: ExitFailure `liftM` execvp_no_vtalarm c_c c_args pid -> do ecode <- smart_wait pid if ecode == 0 then return ExitSuccess else return $ ExitFailure ecode foreign import ccall unsafe "static unistd.h dup2" c_dup2 :: Int -> Int -> IO Int foreign import ccall unsafe "static compat.h smart_wait" smart_wait :: Int -> IO Int foreign import ccall unsafe "static compat.h open_read" open_read :: CString -> IO Int foreign import ccall unsafe "static compat.h open_write" open_write :: CString -> IO Int foreign import ccall unsafe "static unistd.h fork" c_fork :: IO Int foreign import ccall unsafe "static unistd.h execvp_no_vtalarm" execvp_no_vtalarm :: CString -> Ptr CString -> IO Int #endif \end{code}