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
28 #ifdef __GLASGOW_HASKELL__
31 import Control.Exception ( bracket )
49 -- ---------------------------------------------------------------------------
50 -- getArgs, getProgName, getEnv
52 -- | Computation 'getArgs' returns a list of the program's command
53 -- line arguments (not including the program name).
55 #ifdef __GLASGOW_HASKELL__
56 getArgs :: IO [String]
59 alloca $ \ p_argv -> do
60 getProgArgv p_argc p_argv
61 p <- fromIntegral `liftM` peek p_argc
63 peekArray (p - 1) (advancePtr argv 1) >>= mapM peekCString
66 foreign import ccall unsafe "getProgArgv"
67 getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
70 Computation 'getProgName' returns the name of the program as it was
73 However, this is hard-to-impossible to implement on some non-Unix
74 OSes, so instead, for maximum portability, we just return the leafname
75 of the program as invoked. Even then there are some differences
76 between platforms: on Windows, for example, a program invoked as foo
77 is probably really @FOO.EXE@, and that is what 'getProgName' will return.
79 getProgName :: IO String
82 alloca $ \ p_argv -> do
83 getProgArgv p_argc p_argv
87 unpackProgName :: Ptr (Ptr CChar) -> IO String -- argv[0]
88 unpackProgName argv = do
89 s <- peekElemOff argv 0 >>= peekCString
92 basename :: String -> String
97 | isPathSeparator x = go xs xs
98 | otherwise = go acc xs
100 isPathSeparator :: Char -> Bool
101 isPathSeparator '/' = True
102 #ifdef mingw32_TARGET_OS
103 isPathSeparator '\\' = True
105 isPathSeparator _ = False
108 -- | Computation 'getEnv' @var@ returns the value
109 -- of the environment variable @var@.
111 -- This computation may fail with:
113 -- * 'System.IO.Error.isDoesNotExistError' if the environment variable
116 getEnv :: String -> IO String
118 withCString name $ \s -> do
119 litstring <- c_getenv s
120 if litstring /= nullPtr
121 then peekCString litstring
122 else ioException (IOError Nothing NoSuchThing "getEnv"
123 "no environment variable" (Just name))
125 foreign import ccall unsafe "getenv"
126 c_getenv :: CString -> IO (Ptr CChar)
129 'withArgs' @args act@ - while executing action @act@, have 'getArgs'
132 withArgs :: [String] -> IO a -> IO a
134 p <- System.Environment.getProgName
138 'withProgName' @name act@ - while executing action @act@,
139 have 'getProgName' return @name@.
141 withProgName :: String -> IO a -> IO a
142 withProgName nm act = do
143 xs <- System.Environment.getArgs
146 -- Worker routine which marshals and replaces an argv vector for
147 -- the duration of an action.
149 withArgv :: [String] -> IO a -> IO a
150 withArgv new_args act = do
151 pName <- System.Environment.getProgName
152 existing_args <- System.Environment.getArgs
153 bracket (setArgs new_args)
154 (\argv -> do setArgs (pName:existing_args); freeArgv argv)
157 freeArgv :: Ptr CString -> IO ()
159 size <- lengthArray0 nullPtr argv
160 sequence_ [peek (argv `advancePtr` i) >>= free | i <- [size, size-1 .. 0]]
163 setArgs :: [String] -> IO (Ptr CString)
165 vs <- mapM newCString argv >>= newArray0 nullPtr
166 setArgsPrim (length argv) vs
169 foreign import ccall unsafe "setProgArgv"
170 setArgsPrim :: Int -> Ptr CString -> IO ()
171 #endif /* __GLASGOW_HASKELL__ */