{-# LINE 1 "libraries\\base\\System\\Environment\\Blank.hsc" #-} {-# LANGUAGE Safe #-} {-# LANGUAGE CPP #-} {-# LANGUAGE CApiFFI #-} ----------------------------------------------------------------------------- -- | -- Module : System.Environment.Blank -- Copyright : (c) Habib Alamin 2017 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : provisional -- Portability : portable -- -- A setEnv implementation that allows blank environment variables. Mimics -- the `System.Posix.Env` module from the @unix@ package, but with support -- for Windows too. -- -- The matrix of platforms that: -- -- * support @putenv("FOO")@ to unset environment variables, -- * support @putenv("FOO=")@ to unset environment variables or set them -- to blank values, -- * support @unsetenv@ to unset environment variables, -- * support @setenv@ to set environment variables, -- * etc. -- -- is very complicated. Some platforms don't support unsetting of environment -- variables at all. -- ----------------------------------------------------------------------------- module System.Environment.Blank ( module System.Environment, getEnv, getEnvDefault, setEnv, unsetEnv, ) where import Foreign.C {-# LINE 44 "libraries\\base\\System\\Environment\\Blank.hsc" #-} import Foreign.Ptr import GHC.Windows import Control.Monad {-# LINE 50 "libraries\\base\\System\\Environment\\Blank.hsc" #-} import GHC.IO.Exception import System.IO.Error import Control.Exception.Base import Data.Maybe import System.Environment ( getArgs, getProgName, getExecutablePath, withArgs, withProgName, getEnvironment ) {-# LINE 67 "libraries\\base\\System\\Environment\\Blank.hsc" #-} -- TODO: include windows_cconv.h when it's merged, instead of duplicating -- this C macro block. {-# LINE 71 "libraries\\base\\System\\Environment\\Blank.hsc" #-} {-# LINE 74 "libraries\\base\\System\\Environment\\Blank.hsc" #-} # define WINDOWS_CCONV ccall {-# LINE 78 "libraries\\base\\System\\Environment\\Blank.hsc" #-} {-# LINE 79 "libraries\\base\\System\\Environment\\Blank.hsc" #-} throwInvalidArgument :: String -> IO a throwInvalidArgument from = throwIO (mkIOError InvalidArgument from Nothing Nothing) -- | Similar to 'System.Environment.lookupEnv'. getEnv :: String -> IO (Maybe String) {-# LINE 89 "libraries\\base\\System\\Environment\\Blank.hsc" #-} getEnv = (<$> getEnvironment) . lookup {-# LINE 93 "libraries\\base\\System\\Environment\\Blank.hsc" #-} -- | Get an environment value or a default value. getEnvDefault :: String {- ^ variable name -} -> String {- ^ fallback value -} -> IO String {- ^ variable value or fallback value -} getEnvDefault name fallback = fromMaybe fallback <$> getEnv name -- | Like 'System.Environment.setEnv', but allows blank environment values -- and mimics the function signature of 'System.Posix.Env.setEnv' from the -- @unix@ package. setEnv :: String {- ^ variable name -} -> String {- ^ variable value -} -> Bool {- ^ overwrite -} -> IO () setEnv key_ value_ overwrite | null key = throwInvalidArgument "setEnv" | '=' `elem` key = throwInvalidArgument "setEnv" | otherwise = if overwrite then setEnv_ key value else do env_var <- getEnv key case env_var of Just _ -> return () Nothing -> setEnv_ key value where key = takeWhile (/= '\NUL') key_ value = takeWhile (/= '\NUL') value_ setEnv_ :: String -> String -> IO () {-# LINE 126 "libraries\\base\\System\\Environment\\Blank.hsc" #-} setEnv_ key value = withCWString key $ \k -> withCWString value $ \v -> do success <- c_SetEnvironmentVariable k v unless success (throwGetLastError "setEnv") foreign import WINDOWS_CCONV unsafe "windows.h SetEnvironmentVariableW" c_SetEnvironmentVariable :: LPTSTR -> LPTSTR -> IO Bool {-# LINE 142 "libraries\\base\\System\\Environment\\Blank.hsc" #-} -- | Like 'System.Environment.unsetEnv', but allows for the removal of -- blank environment variables. May throw an exception if the underlying -- platform doesn't support unsetting of environment variables. unsetEnv :: String -> IO () {-# LINE 148 "libraries\\base\\System\\Environment\\Blank.hsc" #-} unsetEnv key = withCWString key $ \k -> do success <- c_SetEnvironmentVariable k nullPtr unless success $ do -- We consider unsetting an environment variable that does not exist not as -- an error, hence we ignore eRROR_ENVVAR_NOT_FOUND. err <- c_GetLastError unless (err == eRROR_ENVVAR_NOT_FOUND) $ do throwGetLastError "unsetEnv" eRROR_ENVVAR_NOT_FOUND :: DWORD eRROR_ENVVAR_NOT_FOUND = 203 foreign import WINDOWS_CCONV unsafe "windows.h GetLastError" c_GetLastError:: IO DWORD {-# LINE 194 "libraries\\base\\System\\Environment\\Blank.hsc" #-}