1 % -----------------------------------------------------------------------------
2 % $Id: System.lhs,v 1.28 2001/01/11 17:25:57 simonmar Exp $
4 % (c) The University of Glasgow, 1994-2000
7 \section[System]{Module @System@}
10 {-# OPTIONS -#include "cbits/stgio.h" #-}
13 ExitCode(ExitSuccess,ExitFailure)
14 , getArgs -- :: IO [String]
15 , getProgName -- :: IO String
16 , getEnv -- :: String -> IO String
17 , system -- :: String -> IO ExitCode
18 , exitWith -- :: ExitCode -> IO a
19 , exitFailure -- :: IO a
28 import PrelMarshalArray
31 import PrelIOBase ( IOException(..), ioException,
32 IOErrorType(..), constructErrorAndFailWithInfo )
33 import PrelByteArr ( ByteArray )
36 %*********************************************************
38 \subsection{The @ExitCode@ type}
40 %*********************************************************
42 The $ExitCode$ type defines the exit codes that a program
43 can return. $ExitSuccess$ indicates successful termination;
44 and $ExitFailure code$ indicates program failure
45 with value {\em code}. The exact interpretation of {\em code}
46 is operating-system dependent. In particular, some values of
47 {\em code} may be prohibited (e.g. 0 on a POSIX-compliant system).
50 data ExitCode = ExitSuccess | ExitFailure Int
51 deriving (Eq, Ord, Read, Show)
55 Computation $getArgs$ returns a list of the program's command
56 line arguments (not including the program name).
59 getArgs :: IO [String]
60 getArgs = unpackArgv primArgv primArgc
62 foreign import ccall "get_prog_argv" unsafe primArgv :: Ptr (Ptr CChar)
63 foreign import ccall "get_prog_argc" unsafe primArgc :: Int
66 Computation $getProgName$ returns the name of the program
70 getProgName :: IO String
71 getProgName = unpackProgName primArgv
74 Computation $getEnv var$ returns the value
75 of the environment variable {\em var}.
77 This computation may fail with
80 The environment variable does not exist.
84 getEnv :: String -> IO String
86 withUnsafeCString name $ \s -> do
87 litstring <- _getenv s
88 if litstring /= nullPtr
89 then peekCString litstring
90 else ioException (IOError Nothing NoSuchThing "getEnv"
91 "no environment variable" (Just name))
93 foreign import ccall "getenv" unsafe _getenv :: UnsafeCString -> IO (Ptr CChar)
96 Computation $system cmd$ returns the exit code
97 produced when the operating system processes the command {\em cmd}.
99 This computation may fail with
101 \item $PermissionDenied$
102 The process has insufficient privileges to perform the operation.
103 \item $ResourceExhausted$
104 Insufficient resources are available to perform the operation.
105 \item $UnsupportedOperation$
106 The implementation does not support system calls.
110 system :: String -> IO ExitCode
111 system "" = ioException (IOError Nothing InvalidArgument "system" "null command" Nothing)
113 withUnsafeCString cmd $ \s -> do
114 status <- primSystem s
116 0 -> return ExitSuccess
117 -1 -> constructErrorAndFailWithInfo "system" cmd
118 n -> return (ExitFailure n)
120 foreign import ccall "systemCmd" unsafe primSystem :: UnsafeCString -> IO Int
123 @exitWith code@ terminates the program, returning {\em code} to the program's caller.
124 Before it terminates, any open or semi-closed handles are first closed.
127 exitWith :: ExitCode -> IO a
128 exitWith ExitSuccess = do
130 ioException (IOError Nothing OtherError "exitWith" "exit should not return" Nothing)
132 exitWith (ExitFailure n)
133 | n == 0 = ioException (IOError Nothing InvalidArgument "exitWith" "ExitFailure 0" Nothing)
136 ioException (IOError Nothing OtherError "exitWith" "exit should not return" Nothing)
138 -- NOTE: shutdownHaskellAndExit must be called "safe", because it *can*
139 -- re-enter Haskell land through finalizers.
140 foreign import ccall "shutdownHaskellAndExit" primExit :: Int -> IO ()
143 exitFailure = exitWith (ExitFailure 1)
147 %*********************************************************
149 \subsection{Local utilities}
151 %*********************************************************
154 unpackArgv :: Ptr (Ptr CChar) -> Int -> IO [String] -- argv[1 .. argc-1]
155 unpackArgv argv argc = peekArray argc argv >>= mapM peekCString
157 unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
158 unpackProgName argv = do
159 s <- peekElemOff argv 0 >>= peekCString
160 return (de_slash "" s)
162 -- re-start accumulating at every '/'
163 de_slash :: String -> String -> String
164 de_slash acc [] = reverse acc
165 de_slash _acc ('/':xs) = de_slash [] xs
166 de_slash acc (x:xs) = de_slash (x:acc) xs