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
( bracket )
52 -- ---------------------------------------------------------------------------
53 -- getArgs, getProgName, getEnv
55 -- | Computation 'getArgs' returns a list of the program's command
56 -- line arguments (not including the program name).
58 #ifdef __GLASGOW_HASKELL__
59 getArgs :: IO [String]
62 alloca
$ \ p_argv
-> do
63 getProgArgv p_argc p_argv
64 p
<- fromIntegral `
liftM` peek p_argc
66 peekArray
(p
- 1) (advancePtr argv
1) >>= mapM peekCString
69 foreign import ccall unsafe
"getProgArgv"
70 getProgArgv
:: Ptr CInt
-> Ptr
(Ptr CString
) -> IO ()
73 Computation 'getProgName' returns the name of the program as it was
76 However, this is hard-to-impossible to implement on some non-Unix
77 OSes, so instead, for maximum portability, we just return the leafname
78 of the program as invoked. Even then there are some differences
79 between platforms: on Windows, for example, a program invoked as foo
80 is probably really @FOO.EXE@, and that is what 'getProgName' will return.
82 getProgName :: IO String
85 alloca
$ \ p_argv
-> do
86 getProgArgv p_argc p_argv
90 unpackProgName
:: Ptr
(Ptr CChar
) -> IO String -- argv[0]
91 unpackProgName argv
= do
92 s
<- peekElemOff argv
0 >>= peekCString
95 basename
:: String -> String
100 | isPathSeparator x
= go xs xs
101 |
otherwise = go acc xs
103 isPathSeparator
:: Char -> Bool
104 isPathSeparator
'/' = True
105 #ifdef mingw32_HOST_OS
106 isPathSeparator
'\\' = True
108 isPathSeparator _
= False
111 -- | Computation 'getEnv' @var@ returns the value
112 -- of the environment variable @var@.
114 -- This computation may fail with:
116 -- * 'System.IO.Error.isDoesNotExistError' if the environment variable
119 getEnv :: String -> IO String
121 withCString name
$ \s
-> do
122 litstring
<- c_getenv s
123 if litstring
/= nullPtr
124 then peekCString litstring
125 else ioException
(IOError Nothing NoSuchThing
"getEnv"
126 "no environment variable" (Just name
))
128 foreign import ccall unsafe
"getenv"
129 c_getenv
:: CString
-> IO (Ptr CChar
)
132 'withArgs' @args act@ - while executing action @act@, have 'getArgs'
135 withArgs
:: [String] -> IO a
-> IO a
137 p
<- System
.Environment
.getProgName
141 'withProgName' @name act@ - while executing action @act@,
142 have 'getProgName' return @name@.
144 withProgName
:: String -> IO a
-> IO a
145 withProgName nm act
= do
146 xs
<- System
.Environment
.getArgs
149 -- Worker routine which marshals and replaces an argv vector for
150 -- the duration of an action.
152 withArgv
:: [String] -> IO a
-> IO a
153 withArgv new_args act
= do
154 pName
<- System
.Environment
.getProgName
155 existing_args
<- System
.Environment
.getArgs
156 bracket (setArgs new_args
)
157 (\argv
-> do setArgs
(pName
:existing_args
); freeArgv argv
)
160 freeArgv
:: Ptr CString
-> IO ()
162 size
<- lengthArray0 nullPtr argv
163 sequence_ [peek
(argv `advancePtr` i
) >>= free | i
<- [size
, size
-1 .. 0]]
166 setArgs
:: [String] -> IO (Ptr CString
)
168 vs
<- mapM newCString argv
>>= newArray0 nullPtr
169 setArgsPrim
(genericLength argv
) vs
172 foreign import ccall unsafe
"setProgArgv"
173 setArgsPrim
:: CInt
-> Ptr CString
-> IO ()
175 -- |'getEnvironment' retrieves the entire environment as a
176 -- list of @(key,value)@ pairs.
178 -- If an environment entry does not contain an @\'=\'@ character,
179 -- the @key@ is the whole entry and the @value@ is the empty string.
181 getEnvironment
:: IO [(String, String)]
183 pBlock
<- getEnvBlock
184 if pBlock
== nullPtr
then return []
186 stuff
<- peekArray0 nullPtr pBlock
>>= mapM peekCString
187 return (map divvy stuff
)
190 case break (=='=') str
of
191 (xs
,[]) -> (xs
,[]) -- don't barf (like Posix.getEnvironment)
192 (name
,_
:value) -> (name
,value)
194 foreign import ccall unsafe
"__hscore_environ"
195 getEnvBlock
:: IO (Ptr CString
)
196 #endif
/* __GLASGOW_HASKELL__
*/