1
1
{-# LANGUAGE CApiFFI #-}
2
- {-# LANGUAGE Safe #-}
2
+ {-# LANGUAGE Trustworthy #-}
3
3
4
4
-----------------------------------------------------------------------------
5
5
-- |
@@ -21,23 +21,29 @@ module System.Posix.Env.ByteString (
21
21
, getEnvDefault
22
22
, getEnvironmentPrim
23
23
, getEnvironment
24
+ , setEnvironment
24
25
, putEnv
25
26
, setEnv
26
- , unsetEnv
27
+ , unsetEnv
28
+ , clearEnv
27
29
28
30
-- * Program arguments
29
31
, getArgs
30
32
) where
31
33
32
34
#include "HsUnix.h"
33
35
36
+ import Control.Monad
34
37
import Foreign
35
38
import Foreign.C
36
39
import Data.Maybe ( fromMaybe )
37
40
41
+ import System.Posix.Env ( clearEnv )
38
42
import qualified Data.ByteString as B
39
43
import qualified Data.ByteString.Char8 as BC
40
44
import Data.ByteString (ByteString )
45
+ import Data.ByteString.Internal (ByteString (PS ), memcpy )
46
+ import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr )
41
47
42
48
-- | 'getEnv' looks up a variable in the environment.
43
49
@@ -96,6 +102,18 @@ getEnvironment = do
96
102
| BC. head y == ' =' = (x,B. tail y)
97
103
| otherwise = error $ " getEnvironment: insane variable " ++ BC. unpack x
98
104
105
+ -- | 'setEnvironment' resets the entire environment to the given list of
106
+ -- @(key,value)@ pairs.
107
+ --
108
+ -- @since 2.8.0.0
109
+ setEnvironment ::
110
+ [(ByteString ,ByteString )] {- ^ @[(key,value)]@ -} ->
111
+ IO ()
112
+ setEnvironment env = do
113
+ clearEnv
114
+ forM_ env $ \ (key,value) ->
115
+ setEnv key value True {- overwrite-}
116
+
99
117
-- | The 'unsetEnv' function deletes all instances of the variable name
100
118
-- from the environment.
101
119
@@ -116,15 +134,25 @@ foreign import capi unsafe "HsUnix.h unsetenv"
116
134
c_unsetenv :: CString -> IO ()
117
135
# endif
118
136
#else
119
- unsetEnv name = putEnv (name ++ " =" )
137
+ unsetEnv name = putEnv (name <> BC. pack " =" )
120
138
#endif
121
139
122
140
-- | 'putEnv' function takes an argument of the form @name=value@
123
141
-- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
124
142
125
143
putEnv :: ByteString {- ^ "key=value" -} -> IO ()
126
- putEnv keyvalue = B. useAsCString keyvalue $ \ s ->
127
- throwErrnoIfMinus1_ " putenv" (c_putenv s)
144
+ putEnv (PS fp _ l) = do
145
+ -- https://pubs.opengroup.org/onlinepubs/009696899/functions/putenv.html
146
+ --
147
+ -- "the string pointed to by string shall become part of the environment,
148
+ -- so altering the string shall change the environment. The space used by
149
+ -- string is no longer used once a new string which defines name is passed to putenv()."
150
+ --
151
+ -- hence we must not free the buffer
152
+ buf <- mallocBytes (l+ 1 )
153
+ memcpy buf (unsafeForeignPtrToPtr fp) l
154
+ pokeByteOff buf l (0 :: Word8 )
155
+ throwErrnoIfMinus1_ " putenv" (c_putenv (castPtr buf))
128
156
129
157
foreign import ccall unsafe " putenv"
130
158
c_putenv :: CString -> IO CInt
0 commit comments