1 -----------------------------------------------------------------------------
3 -- Module : System.Environment
4 -- Copyright : (c) The University of Glasgow 2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : provisional
9 -- Portability : portable
11 -- Miscellaneous information about the system environment.
13 -----------------------------------------------------------------------------
15 module System.Environment
17 getArgs, -- :: IO [String]
18 getProgName, -- :: IO String
19 getEnv, -- :: String -> IO String
24 #ifdef __GLASGOW_HASKELL__
31 #ifdef __GLASGOW_HASKELL__
35 import Control.Exception.Base ( bracket )
38 import GHC.IO.Exception
53 -- ---------------------------------------------------------------------------
54 -- getArgs, getProgName, getEnv
56 -- | Computation 'getArgs' returns a list of the program's command
57 -- line arguments (not including the program name).
59 #ifdef __GLASGOW_HASKELL__
60 getArgs :: IO [String]
63 alloca $ \ p_argv -> do
64 getProgArgv p_argc p_argv
65 p <- fromIntegral `liftM` peek p_argc
67 peekArray (p - 1) (advancePtr argv 1) >>= mapM peekCString
70 foreign import ccall unsafe "getProgArgv"
71 getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
74 Computation 'getProgName' returns the name of the program as it was
77 However, this is hard-to-impossible to implement on some non-Unix
78 OSes, so instead, for maximum portability, we just return the leafname
79 of the program as invoked. Even then there are some differences
80 between platforms: on Windows, for example, a program invoked as foo
81 is probably really @FOO.EXE@, and that is what 'getProgName' will return.
83 getProgName :: IO String
86 alloca $ \ p_argv -> do
87 getProgArgv p_argc p_argv
91 unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
92 unpackProgName argv = do
93 s <- peekElemOff argv 0 >>= peekCString
96 basename :: String -> String
101 | isPathSeparator x = go xs xs
102 | otherwise = go acc xs
104 isPathSeparator :: Char -> Bool
105 isPathSeparator '/' = True
106 #ifdef mingw32_HOST_OS
107 isPathSeparator '\\' = True
109 isPathSeparator _ = False
112 -- | Computation 'getEnv' @var@ returns the value
113 -- of the environment variable @var@.
115 -- This computation may fail with:
117 -- * 'System.IO.Error.isDoesNotExistError' if the environment variable
120 getEnv :: String -> IO String
122 withCString name $ \s -> do
123 litstring <- c_getenv s
124 if litstring /= nullPtr
125 then peekCString litstring
126 else ioException (IOError Nothing NoSuchThing "getEnv"
127 "no environment variable" Nothing (Just name))
129 foreign import ccall unsafe "getenv"
130 c_getenv :: CString -> IO (Ptr CChar)
133 'withArgs' @args act@ - while executing action @act@, have 'getArgs'
136 withArgs :: [String] -> IO a -> IO a
138 p <- System.Environment.getProgName
142 'withProgName' @name act@ - while executing action @act@,
143 have 'getProgName' return @name@.
145 withProgName :: String -> IO a -> IO a
146 withProgName nm act = do
147 xs <- System.Environment.getArgs
150 -- Worker routine which marshals and replaces an argv vector for
151 -- the duration of an action.
153 withArgv :: [String] -> IO a -> IO a
154 withArgv new_args act = do
155 pName <- System.Environment.getProgName
156 existing_args <- System.Environment.getArgs
157 bracket (setArgs new_args)
158 (\argv -> do _ <- setArgs (pName:existing_args)
162 freeArgv :: Ptr CString -> IO ()
164 size <- lengthArray0 nullPtr argv
165 sequence_ [peek (argv `advancePtr` i) >>= free | i <- [size, size-1 .. 0]]
168 setArgs :: [String] -> IO (Ptr CString)
170 vs <- mapM newCString argv >>= newArray0 nullPtr
171 setArgsPrim (genericLength argv) vs
174 foreign import ccall unsafe "setProgArgv"
175 setArgsPrim :: CInt -> Ptr CString -> IO ()
177 -- |'getEnvironment' retrieves the entire environment as a
178 -- list of @(key,value)@ pairs.
180 -- If an environment entry does not contain an @\'=\'@ character,
181 -- the @key@ is the whole entry and the @value@ is the empty string.
183 getEnvironment :: IO [(String, String)]
185 pBlock <- getEnvBlock
186 if pBlock == nullPtr then return []
188 stuff <- peekArray0 nullPtr pBlock >>= mapM peekCString
189 return (map divvy stuff)
192 case break (=='=') str of
193 (xs,[]) -> (xs,[]) -- don't barf (like Posix.getEnvironment)
194 (name,_:value) -> (name,value)
196 foreign import ccall unsafe "__hscore_environ"
197 getEnvBlock :: IO (Ptr CString)
198 #endif /* __GLASGOW_HASKELL__ */