1 -- -----------------------------------------------------------------------------
2 -- $Id: System.lhs,v 1.30 2001/05/18 16:54:05 simonmar Exp $
4 -- (c) The University of Glasgow, 1994-2000
10 ExitCode(ExitSuccess,ExitFailure)
11 , getArgs -- :: IO [String]
12 , getProgName -- :: IO String
13 , getEnv -- :: String -> IO String
14 , system -- :: String -> IO ExitCode
15 , exitWith -- :: ExitCode -> IO a
16 , exitFailure -- :: IO a
24 import PrelMarshalArray
27 import PrelIOBase ( IOException(..), ioException, IOErrorType(..))
29 -- -----------------------------------------------------------------------------
32 -- The `ExitCode' type defines the exit codes that a program
33 -- can return. `ExitSuccess' indicates successful termination;
34 -- and `ExitFailure code' indicates program failure
35 -- with value `code'. The exact interpretation of `code'
36 -- is operating-system dependent. In particular, some values of
37 -- `code' may be prohibited (e.g. 0 on a POSIX-compliant system).
39 data ExitCode = ExitSuccess | ExitFailure Int
40 deriving (Eq, Ord, Read, Show)
43 -- Computation `getArgs' returns a list of the program's command
44 -- line arguments (not including the program name).
46 getArgs :: IO [String]
47 getArgs = unpackArgv primArgv primArgc
49 foreign import ccall "get_prog_argv" unsafe primArgv :: Ptr (Ptr CChar)
50 foreign import ccall "get_prog_argc" unsafe primArgc :: Int
52 -- Computation `getProgName' returns the name of the program
55 getProgName :: IO String
56 getProgName = unpackProgName primArgv
58 -- Computation `getEnv var' returns the value
59 -- of the environment variable {\em var}.
61 -- This computation may fail with
62 -- NoSuchThing: The environment variable does not exist.
64 getEnv :: String -> IO String
66 withUnsafeCString name $ \s -> do
67 litstring <- _getenv s
68 if litstring /= nullPtr
69 then peekCString litstring
70 else ioException (IOError Nothing NoSuchThing "getEnv"
71 "no environment variable" (Just name))
73 foreign import ccall "getenv" unsafe _getenv :: UnsafeCString -> IO (Ptr CChar)
75 -- ---------------------------------------------------------------------------
78 -- Computation `system cmd' returns the exit code
79 -- produced when the operating system processes the command {\em cmd}.
81 -- This computation may fail with
83 -- The process has insufficient privileges to perform the operation.
85 -- Insufficient resources are available to perform the operation.
86 -- UnsupportedOperation
87 -- The implementation does not support system calls.
89 system :: String -> IO ExitCode
90 system "" = ioException (IOError Nothing InvalidArgument "system" "null command" Nothing)
92 withUnsafeCString cmd $ \s -> do
93 status <- throwErrnoIfMinus1 "system" (primSystem s)
95 0 -> return ExitSuccess
96 n -> return (ExitFailure n)
98 foreign import ccall "systemCmd" unsafe primSystem :: UnsafeCString -> IO Int
100 -- ---------------------------------------------------------------------------
103 -- `exitWith code' terminates the program, returning `code' to the
104 -- program's caller. Before it terminates, any open or semi-closed
105 -- handles are first closed.
107 exitWith :: ExitCode -> IO a
108 exitWith ExitSuccess = do
110 ioException (IOError Nothing OtherError "exitWith" "exit should not return" Nothing)
112 exitWith (ExitFailure n)
113 | n == 0 = ioException (IOError Nothing InvalidArgument "exitWith" "ExitFailure 0" Nothing)
116 ioException (IOError Nothing OtherError "exitWith" "exit should not return" Nothing)
118 -- NOTE: shutdownHaskellAndExit must be called "safe", because it *can*
119 -- re-enter Haskell land through finalizers.
120 foreign import ccall "shutdownHaskellAndExit" primExit :: Int -> IO ()
123 exitFailure = exitWith (ExitFailure 1)
125 -- ---------------------------------------------------------------------------
128 unpackArgv :: Ptr (Ptr CChar) -> Int -> IO [String] -- argv[1 .. argc-1]
130 = peekArray (argc-1) (advancePtr argv 1) >>= mapM peekCString
132 unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
133 unpackProgName argv = do
134 s <- peekElemOff argv 0 >>= peekCString
135 return (de_slash "" s)
137 -- re-start accumulating at every '/'
138 de_slash :: String -> String -> String
139 de_slash acc [] = reverse acc
140 de_slash _acc ('/':xs) = de_slash [] xs
141 de_slash acc (x:xs) = de_slash (x:acc) xs