@@ -129,6 +129,133 @@ fn setenv(n: str, v: str) {
129
129
global_env:: setenv( n, v)
130
130
}
131
131
132
+ mod global_env {
133
+ #[ doc = "Internal module for serializing access to getenv/setenv" ] ;
134
+
135
+ export getenv;
136
+ export setenv;
137
+
138
+ native mod rustrt {
139
+ fn rust_global_env_chan_ptr( ) -> * libc : : uintptr_t;
140
+ }
141
+
142
+ enum msg {
143
+ msg_getenv( str, comm:: chan < option < str > > ) ,
144
+ msg_setenv( str, str, comm:: chan < ( ) > )
145
+ }
146
+
147
+ fn getenv( n: str) -> option < str > {
148
+ let env_ch = get_global_env_chan( ) ;
149
+ let po = comm:: port( ) ;
150
+ comm:: send( env_ch, msg_getenv( n, comm:: chan( po) ) ) ;
151
+ comm:: recv( po)
152
+ }
153
+
154
+ fn setenv( n: str, v: str) {
155
+ let env_ch = get_global_env_chan( ) ;
156
+ let po = comm:: port( ) ;
157
+ comm:: send( env_ch, msg_setenv( n, v, comm:: chan( po) ) ) ;
158
+ comm:: recv( po)
159
+ }
160
+
161
+ fn get_global_env_chan ( ) -> comm:: chan < msg > {
162
+ let global_ptr = rustrt : : rust_global_env_chan_ptr( ) ;
163
+ let builder_fn = { ||
164
+ let builder = task: : builder( ) ;
165
+ task:: unsupervise( builder) ;
166
+ task:: set_opts( builder, {
167
+ sched : some ( {
168
+ mode : task:: single_threaded,
169
+ // FIXME: This would be a good place to use
170
+ // a very small native stack
171
+ native_stack_size : none
172
+ } )
173
+ with task:: get_opts( builder)
174
+ } ) ;
175
+ builder
176
+ } ;
177
+ unsafe {
178
+ priv:: chan_from_global_ptr(
179
+ global_ptr, builder_fn, global_env_task)
180
+ }
181
+ }
182
+
183
+ fn global_env_task( msg_po: comm:: port<msg>) unsafe {
184
+ priv:: weaken_task { |weak_po|
185
+ loop {
186
+ alt comm:: select2( msg_po, weak_po) {
187
+ either:: left( msg_getenv( n, resp_ch) ) {
188
+ comm:: send( resp_ch, impl:: getenv( n) )
189
+ }
190
+ either:: left( msg_setenv( n, v, resp_ch) ) {
191
+ comm:: send( resp_ch, impl :: setenv( n, v) )
192
+ }
193
+ either:: right( _) {
194
+ break ;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ mod impl {
202
+
203
+ #[ cfg( target_os = "linux") ]
204
+ #[ cfg( target_os = "macos") ]
205
+ #[ cfg( target_os = "freebsd") ]
206
+ fn getenv( n: str ) -> option<str > unsafe {
207
+ let s = str :: as_c_str( n, libc:: getenv) ;
208
+ ret if unsafe :: reinterpret_cast( s) == 0 {
209
+ option:: none:: <str >
210
+ } else {
211
+ let s = unsafe :: reinterpret_cast( s) ;
212
+ option:: some:: <str >( str :: unsafe :: from_buf( s) )
213
+ } ;
214
+ }
215
+
216
+ #[ cfg( target_os = "win32") ]
217
+ fn getenv( n: str ) -> option<str > unsafe {
218
+ import libc:: types:: os:: arch:: extra:: * ;
219
+ import libc:: funcs:: extra:: kernel32:: * ;
220
+ import win32:: * ;
221
+ as_utf16_p( n) { |u|
222
+ fill_utf16_buf_and_decode( ) { |buf, sz|
223
+ GetEnvironmentVariableW ( u, buf, sz)
224
+ }
225
+ }
226
+ }
227
+
228
+
229
+ #[ cfg( target_os = "linux") ]
230
+ #[ cfg( target_os = "macos") ]
231
+ #[ cfg( target_os = "freebsd") ]
232
+ fn setenv( n: str , v: str ) {
233
+
234
+ // FIXME: remove this when export globs work properly.
235
+ import libc:: funcs:: posix01:: unistd:: setenv;
236
+ str :: as_c_str( n) { |nbuf|
237
+ str:: as_c_str( v) { |vbuf|
238
+ setenv( nbuf, vbuf, 1i32 ) ;
239
+ }
240
+ }
241
+ }
242
+
243
+
244
+ #[ cfg( target_os = "win32") ]
245
+ fn setenv( n: str , v: str ) {
246
+ // FIXME: remove imports when export globs work properly.
247
+ import libc:: funcs:: extra:: kernel32:: * ;
248
+ import win32:: * ;
249
+ as_utf16_p( n) { |nbuf|
250
+ as_utf16_p( v) { |vbuf|
251
+ SetEnvironmentVariableW ( nbuf, vbuf) ;
252
+ }
253
+ }
254
+ }
255
+
256
+ }
257
+ }
258
+
132
259
fn fdopen( fd: c_int) -> * FILE {
133
260
ret as_c_charp( "r") { |modebuf|
134
261
libc:: fdopen( fd, modebuf)
0 commit comments