    -----------------------------------------------------------------------------
    -- |
    -- Module      :  System.Cmd
    -- Copyright   :  (c) The University of Glasgow 2001
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  libraries@haskell.org
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- Executing an external command.
    --
    -- This module provides a simple interface for executing external commands.
    -- For a more complex, but more powerful, interface, see the "System.Process"
    -- module.
    --
    -----------------------------------------------------------------------------

    module System.Cmd
        ( system,        -- :: String -> IO ExitCode
          rawSystem,     -- :: FilePath -> [String] -> IO ExitCode
        ) where

    import Prelude

    import System.Exit 	( ExitCode )

    #ifdef __GLASGOW_HASKELL__
    import System.Process
    import GHC.IOBase	( ioException, IOException(..), IOErrorType(..) )
    #if !defined(mingw32_HOST_OS)
    import System.Process.Internals
    import System.Posix.Signals
    #endif
    #endif

    #ifdef __HUGS__
    import Hugs.System
    #endif

    #ifdef __NHC__
    import System (system)
    #endif

    -- ---------------------------------------------------------------------------
    -- system

    {-|
    Computation @system cmd@ returns the exit code
    produced when the operating system processes the command @cmd@.

    This computation may fail with

       * @PermissionDenied@: The process has insufficient privileges to
         perform the operation.

       * @ResourceExhausted@: Insufficient resources are available to
         perform the operation.

       * @UnsupportedOperation@: The implementation does not support
         system calls.

    On Windows, 'system' is implemented using Windows's native system
    call, which ignores the @SHELL@ environment variable, and always
    passes the command to the Windows command interpreter (@CMD.EXE@ or
    @COMMAND.COM@), hence Unixy shell tricks will not work.
    -}
    #ifdef __GLASGOW_HASKELL__
    system :: String -> IO ExitCode
    system "" = ioException (IOError Nothing InvalidArgument "system" "null command" Nothing)
    system str = do
    #if mingw32_HOST_OS
      p <- runCommand str
      waitForProcess p
    #else
      -- The POSIX version of system needs to do some manipulation of signal
      -- handlers.  Since we're going to be synchronously waiting for the child,
      -- we want to ignore ^C in the parent, but handle it the default way
      -- in the child (using SIG_DFL isn't really correct, it should be the
      -- original signal handler, but the GHC RTS will have already set up
      -- its own handler and we don't want to use that).
      old_int  <- installHandler sigINT  Ignore Nothing
      old_quit <- installHandler sigQUIT Ignore Nothing
      (cmd,args) <- commandToProcess str
      p <- runProcessPosix "runCommand" cmd args Nothing Nothing
    		Nothing Nothing Nothing
    		(Just defaultSignal) (Just defaultSignal)
      r <- waitForProcess p
      installHandler sigINT  old_int Nothing
      installHandler sigQUIT old_quit Nothing
      return r
    #endif  /* mingw32_HOST_OS */
    #endif  /* __GLASGOW_HASKELL__ */

    {-|
    The computation @'rawSystem' cmd args@ runs the operating system command
    @cmd@ in such a way that it receives as arguments the @args@ strings
    exactly as given, with no funny escaping or shell meta-syntax expansion.
    It will therefore behave more portably between operating systems than 'system'.

    The return codes and possible failures are the same as for 'system'.
    -}
    rawSystem :: String -> [String] -> IO ExitCode
    #ifdef __GLASGOW_HASKELL__
    rawSystem cmd args = do

    #if mingw32_HOST_OS
      p <- runProcess cmd args Nothing Nothing Nothing Nothing Nothing
      waitForProcess p
    #else
      old_int  <- installHandler sigINT  Ignore Nothing
      old_quit <- installHandler sigQUIT Ignore Nothing
      p <- runProcessPosix "rawSystem" cmd args Nothing Nothing
    		Nothing Nothing Nothing
    		(Just defaultSignal) (Just defaultSignal)
      r <- waitForProcess p
      installHandler sigINT  old_int Nothing
      installHandler sigQUIT old_quit Nothing
      return r
    #endif

    #elif !mingw32_HOST_OS
    -- crude fallback implementation: could do much better than this under Unix
    rawSystem cmd args = system (unwords (map translate (cmd:args)))

    translate :: String -> String
    translate str = '\'' : foldr escape "'" str
      where	escape '\'' = showString "'\\''"
    	escape c    = showChar c
    #else /* mingw32_HOST_OS &&  ! __GLASGOW_HASKELL__ */
    # if __HUGS__
    rawSystem cmd args = system (unwords (cmd : map translate args))
    # else
    rawSystem cmd args = system (unwords (map translate (cmd:args)))
    #endif

    -- copied from System.Process (qv)
    translate :: String -> String
    translate str = '"' : snd (foldr escape (True,"\"") str)
      where	escape '"'  (b,     str) = (True,  '\\' : '"'  : str)
    	escape '\\' (True,  str) = (True,  '\\' : '\\' : str)
    	escape '\\' (False, str) = (False, '\\' : str)
    	escape c    (b,     str) = (False, c : str)
    #endif