1 {-# LANGUAGE CPP, ForeignFunctionInterface #-}
3 -----------------------------------------------------------------------------
5 -- Module : System.Environment
6 -- Copyright : (c) The University of Glasgow 2001
7 -- License : BSD-style (see the file libraries/base/LICENSE)
9 -- Maintainer : libraries@haskell.org
10 -- Stability : provisional
11 -- Portability : portable
13 -- Miscellaneous information about the system environment.
15 -----------------------------------------------------------------------------
17 module System.Environment
19 getArgs, -- :: IO [String]
20 getProgName, -- :: IO String
21 getEnv, -- :: String -> IO String
26 #ifdef __GLASGOW_HASKELL__
33 #ifdef __GLASGOW_HASKELL__
37 import Control.Exception.Base ( bracket )
40 import GHC.IO.Exception
55 -- ---------------------------------------------------------------------------
56 -- getArgs, getProgName, getEnv
58 -- | Computation 'getArgs' returns a list of the program's command
59 -- line arguments (not including the program name).
61 #ifdef __GLASGOW_HASKELL__
62 getArgs :: IO [String]
65 alloca $ \ p_argv -> do
66 getProgArgv p_argc p_argv
67 p <- fromIntegral `liftM` peek p_argc
69 peekArray (p - 1) (advancePtr argv 1) >>= mapM peekCString
72 foreign import ccall unsafe "getProgArgv"
73 getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
76 Computation 'getProgName' returns the name of the program as it was
79 However, this is hard-to-impossible to implement on some non-Unix
80 OSes, so instead, for maximum portability, we just return the leafname
81 of the program as invoked. Even then there are some differences
82 between platforms: on Windows, for example, a program invoked as foo
83 is probably really @FOO.EXE@, and that is what 'getProgName' will return.
85 getProgName :: IO String
88 alloca $ \ p_argv -> do
89 getProgArgv p_argc p_argv
93 unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
94 unpackProgName argv = do
95 s <- peekElemOff argv 0 >>= peekCString
98 basename :: String -> String
103 | isPathSeparator x = go xs xs
104 | otherwise = go acc xs
106 isPathSeparator :: Char -> Bool
107 isPathSeparator '/' = True
108 #ifdef mingw32_HOST_OS
109 isPathSeparator '\\' = True
111 isPathSeparator _ = False
114 -- | Computation 'getEnv' @var@ returns the value
115 -- of the environment variable @var@.
117 -- This computation may fail with:
119 -- * 'System.IO.Error.isDoesNotExistError' if the environment variable
122 getEnv :: String -> IO String
124 withCString name $ \s -> do
125 litstring <- c_getenv s
126 if litstring /= nullPtr
127 then peekCString litstring
128 else ioException (IOError Nothing NoSuchThing "getEnv"
129 "no environment variable" Nothing (Just name))
131 foreign import ccall unsafe "getenv"
132 c_getenv :: CString -> IO (Ptr CChar)
135 'withArgs' @args act@ - while executing action @act@, have 'getArgs'
138 withArgs :: [String] -> IO a -> IO a
140 p <- System.Environment.getProgName
144 'withProgName' @name act@ - while executing action @act@,
145 have 'getProgName' return @name@.
147 withProgName :: String -> IO a -> IO a
148 withProgName nm act = do
149 xs <- System.Environment.getArgs
152 -- Worker routine which marshals and replaces an argv vector for
153 -- the duration of an action.
155 withArgv :: [String] -> IO a -> IO a
156 withArgv new_args act = do
157 pName <- System.Environment.getProgName
158 existing_args <- System.Environment.getArgs
159 bracket (setArgs new_args)
160 (\argv -> do _ <- setArgs (pName:existing_args)
164 freeArgv :: Ptr CString -> IO ()
166 size <- lengthArray0 nullPtr argv
167 sequence_ [peek (argv `advancePtr` i) >>= free | i <- [size, size-1 .. 0]]
170 setArgs :: [String] -> IO (Ptr CString)
172 vs <- mapM newCString argv >>= newArray0 nullPtr
173 setArgsPrim (genericLength argv) vs
176 foreign import ccall unsafe "setProgArgv"
177 setArgsPrim :: CInt -> Ptr CString -> IO ()
179 -- |'getEnvironment' retrieves the entire environment as a
180 -- list of @(key,value)@ pairs.
182 -- If an environment entry does not contain an @\'=\'@ character,
183 -- the @key@ is the whole entry and the @value@ is the empty string.
185 getEnvironment :: IO [(String, String)]
187 pBlock <- getEnvBlock
188 if pBlock == nullPtr then return []
190 stuff <- peekArray0 nullPtr pBlock >>= mapM peekCString
191 return (map divvy stuff)
194 case break (=='=') str of
195 (xs,[]) -> (xs,[]) -- don't barf (like Posix.getEnvironment)
196 (name,_:value) -> (name,value)
198 foreign import ccall unsafe "__hscore_environ"
199 getEnvBlock :: IO (Ptr CString)
200 #endif /* __GLASGOW_HASKELL__ */