aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--System/Posix.hs2
-rw-r--r--System/Posix/Env.hsc111
-rw-r--r--include/HsUnix.h4
3 files changed, 116 insertions, 1 deletions
diff --git a/System/Posix.hs b/System/Posix.hs
index c15bc24..c730294 100644
--- a/System/Posix.hs
+++ b/System/Posix.hs
@@ -19,6 +19,7 @@ module System.Posix (
module System.Posix.Files,
module System.Posix.Unistd,
module System.Posix.IO,
+ module System.Posix.Env,
module System.Posix.Process,
module System.Posix.Terminal,
module System.Posix.Time,
@@ -32,6 +33,7 @@ import System.Posix.Files
import System.Posix.Unistd
import System.Posix.Process
import System.Posix.IO
+import System.Posix.Env
import System.Posix.Terminal
import System.Posix.Time
import System.Posix.User
diff --git a/System/Posix/Env.hsc b/System/Posix/Env.hsc
new file mode 100644
index 0000000..3692a5f
--- /dev/null
+++ b/System/Posix/Env.hsc
@@ -0,0 +1,111 @@
+{-# OPTIONS -fffi #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : System.Posix.Env
+-- Copyright : (c) The University of Glasgow 2002
+-- License : BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : non-portable (requires POSIX)
+--
+-- POSIX environment support
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Env (
+ getEnvVar,
+ getEnvVarDefault,
+ getEnvironmentPrim,
+ getEnvironment,
+ putEnv,
+ setEnv,
+ unsetEnv
+) where
+
+#include "HsUnix.h"
+
+import Foreign.C.Error ( throwErrnoIfMinus1_ )
+import Foreign.C.Types ( CInt )
+import Foreign.C.String
+import Foreign.Marshal.Array
+import Foreign.Ptr
+import Monad ( liftM )
+import Maybe ( fromMaybe )
+
+-- |'getEnvVar' looks up a variable in the environment.
+
+getEnvVar :: String -> IO (Maybe String)
+getEnvVar name = do
+ litstring <- withCString name c_getenv
+ if litstring /= nullPtr
+ then liftM Just $ peekCString litstring
+ else return Nothing
+
+-- |'getEnvVarDefault' is a wrapper around 'getEnvVar' where the
+-- programmer can specify a fallback if the variable is not found
+-- in the environment.
+
+getEnvVarDefault :: String -> String -> IO String
+getEnvVarDefault name fallback = liftM (fromMaybe fallback) (getEnvVar name)
+
+foreign import ccall unsafe "getenv"
+ c_getenv :: CString -> IO CString
+
+getEnvironmentPrim :: IO [String]
+getEnvironmentPrim = do
+ arr <- peekArray0 nullPtr c_environ
+ mapM peekCString arr
+
+foreign import ccall unsafe "__hsunix_environ"
+ c_environ :: Ptr CString
+
+-- |'getEnvironment' retrieves the entire environment as a
+-- list of @(key,value)@ pairs.
+
+getEnvironment :: IO [(String,String)]
+getEnvironment = do
+ env <- getEnvironmentPrim
+ return $ map (dropEq.(break ((==) '='))) env
+ where
+ dropEq (x,'=':ys) = (x,ys)
+ dropEq (x,_) = error $ "getEnvironment: insane variable " ++ x
+
+-- |The 'unsetenv' function deletes all instances of the variable name
+-- from the environment.
+
+unsetEnv :: String -> IO ()
+unsetEnv name = withCString name c_unsetenv
+
+foreign import ccall unsafe "unsetenv"
+ c_unsetenv :: CString -> IO ()
+
+-- |'putEnv' function takes an argument of the form @name=value@
+-- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
+
+putEnv :: String -> IO ()
+putEnv keyvalue = withCString keyvalue $ \s ->
+ throwErrnoIfMinus1_ "putenv" (c_putenv s)
+
+foreign import ccall unsafe "putenv"
+ c_putenv :: CString -> IO CInt
+
+{- |The 'setenv' function inserts or resets the environment variable name in
+ the current environment list. If the variable @name@ does not exist in the
+ list, it is inserted with the given value. If the variable does exist,
+ the argument @overwrite@ is tested; if @overwrite@ is @False@, the variable is
+ not reset, otherwise it is reset to the given value.
+-}
+
+setEnv :: String -> String -> Bool {-overwrite-} -> IO ()
+setEnv key value ovrwrt = do
+ withCString key $ \ keyP ->
+ withCString value $ \ valueP ->
+ throwErrnoIfMinus1_ "putenv" $ c_setenv keyP valueP (toInt ovrwrt)
+ where
+ toInt :: Bool -> CInt
+ toInt True = 1
+ toInt False = 0
+
+foreign import ccall unsafe "setenv"
+ c_setenv :: CString -> CString -> CInt -> IO CInt
diff --git a/include/HsUnix.h b/include/HsUnix.h
index 5488f71..cccbd7b 100644
--- a/include/HsUnix.h
+++ b/include/HsUnix.h
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------------
- * $Id: HsUnix.h,v 1.4 2003/01/17 17:01:14 stolz Exp $
+ * $Id: HsUnix.h,v 1.5 2003/02/28 16:09:16 stolz Exp $
*
* (c) The University of Glasgow 2002
*
@@ -63,6 +63,7 @@
extern int execvpe(char *name, char **argv, char **envp);
extern void pPrPr_disableITimers (void);
+extern char **environ;
#ifndef INLINE
#define INLINE extern inline
@@ -74,6 +75,7 @@ INLINE int __hsunix_wifsignaled (int stat) { return WIFSIGNALED(stat); }
INLINE int __hsunix_wtermsig (int stat) { return WTERMSIG(stat); }
INLINE int __hsunix_wifstopped (int stat) { return WIFSTOPPED(stat); }
INLINE int __hsunix_wstopsig (int stat) { return WSTOPSIG(stat); }
+INLINE char ** __hsunix_environ () { return environ; }
/* O_SYNC doesn't exist on Mac OS X and (at least some versions of) FreeBSD,
fall back to O_FSYNC, which should be the same */