@@ -20,17 +20,54 @@ getArgs = do n <- numArgs
2020 do arg <- getArg i
2121 ga' (arg :: acc) (i+1) n
2222
23+-- Retrieves an value from the environment, if the given key is present,
24+-- otherwise it returns Nothing.
2325getEnv : String -> IO (Maybe String)
2426getEnv key = do
2527 str_ptr <- getEnv'
26− exists <- nullStr str_ptr
27− if exists
28+ is_nil <- nullStr str_ptr
29+ if is_nil
2830 then pure Nothing
2931 else pure (Just str_ptr)
3032 where
3133 getEnv' : IO String
3234 getEnv' = mkForeign (FFun "getenv" [FString] FString) key
3335
36+-- Sets an environment variable with a given value.
37+-- Returns true if the operation was successful.
38+setEnv : String -> String -> IO Bool
39+setEnv key value = do
40+ ok <- mkForeign (FFun "setenv" [FString, FString, FInt] FInt) key value 1
41+ return (ok == 0)
42+
43+-- Unsets an environment variable.
44+-- Returns true if the variable was able to be unset.
45+unsetEnv : String -> IO Bool
46+unsetEnv key = do
47+ ok <- mkForeign (FFun "unsetenv" [FString] FInt) key
48+ return (ok == 0)
49+
50+getEnvironment : IO (List (String, String))
51+getEnvironment = getAllPairs 0 []
52+ where
53+ getEnvPair : Int -> IO String
54+ getEnvPair i = mkForeign (FFun "getEnvPair" [FInt] FString) i
55+
56+ splitEq : String -> (String, String)
57+ splitEq str =
58+ -- FIXME: There has to be a better way to split this up
59+ let (k, v) = break (== '=') str in
60+ let (_, v') = break (/= '=') v in
61+ (k, v')
62+
63+ getAllPairs : Int -> List String -> IO (List (String, String))
64+ getAllPairs n acc = do
65+ envPair <- getEnvPair n
66+ is_nil <- nullStr envPair
67+ if is_nil
68+ then return $ reverse $ map splitEq acc
69+ else getAllPairs (n + 1) (envPair :: acc)
70+
3471exit : Int -> IO ()
3572exit code = mkForeign (FFun "exit" [FInt] FUnit) code
3673