1
+ #[ doc = "Internal module for serializing access to getenv/setenv" ] ;
2
+
3
+ export getenv;
4
+ export setenv;
5
+
6
+ native mod rustrt {
7
+ fn rust_global_env_chan_ptr ( ) -> * libc:: uintptr_t ;
8
+ }
9
+
10
+ enum msg {
11
+ msg_getenv( str , comm:: chan < option < str > > ) ,
12
+ msg_setenv( str , str , comm:: chan < ( ) > )
13
+ }
14
+
15
+ fn getenv ( n : str ) -> option < str > {
16
+ let env_ch = get_global_env_chan ( ) ;
17
+ let po = comm:: port ( ) ;
18
+ comm:: send ( env_ch, msg_getenv ( n, comm:: chan ( po) ) ) ;
19
+ comm:: recv ( po)
20
+ }
21
+
22
+ fn setenv ( n : str , v : str ) {
23
+ let env_ch = get_global_env_chan ( ) ;
24
+ let po = comm:: port ( ) ;
25
+ comm:: send ( env_ch, msg_setenv ( n, v, comm:: chan ( po) ) ) ;
26
+ comm:: recv ( po)
27
+ }
28
+
29
+ fn get_global_env_chan ( ) -> comm:: chan < msg > {
30
+ let global_ptr = rustrt:: rust_global_env_chan_ptr ( ) ;
31
+ let builder_fn = { ||
32
+ let builder = task:: builder ( ) ;
33
+ task:: unsupervise ( builder) ;
34
+ task:: set_opts ( builder, {
35
+ sched: some ( {
36
+ mode: task:: single_threaded,
37
+ // FIXME: This would be a good place to use
38
+ // a very small native stack
39
+ native_stack_size: none
40
+ } )
41
+ with task:: get_opts ( builder)
42
+ } ) ;
43
+ builder
44
+ } ;
45
+ unsafe {
46
+ priv:: chan_from_global_ptr (
47
+ global_ptr, builder_fn, global_env_task)
48
+ }
49
+ }
50
+
51
+ fn global_env_task ( msg_po : comm:: port < msg > ) unsafe {
52
+ priv:: weaken_task { |weak_po|
53
+ loop {
54
+ alt comm:: select2 ( msg_po, weak_po) {
55
+ either:: left ( msg_getenv ( n, resp_ch) ) {
56
+ comm:: send ( resp_ch, impl:: getenv ( n) )
57
+ }
58
+ either:: left ( msg_setenv ( n, v, resp_ch) ) {
59
+ comm:: send ( resp_ch, impl:: setenv ( n, v) )
60
+ }
61
+ either:: right ( _) {
62
+ break ;
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ mod impl {
70
+
71
+ #[ cfg( target_os = "linux" ) ]
72
+ #[ cfg( target_os = "macos" ) ]
73
+ #[ cfg( target_os = "freebsd" ) ]
74
+ fn getenv ( n : str ) -> option < str > unsafe {
75
+ let s = str:: as_c_str ( n, libc:: getenv) ;
76
+ ret if unsafe :: reinterpret_cast ( s) == 0 {
77
+ option:: none :: < str >
78
+ } else {
79
+ let s = unsafe :: reinterpret_cast ( s) ;
80
+ option:: some :: < str > ( str:: unsafe:: from_buf ( s) )
81
+ } ;
82
+ }
83
+
84
+ #[ cfg( target_os = "win32" ) ]
85
+ fn getenv ( n : str ) -> option < str > unsafe {
86
+ import libc:: types:: os:: arch:: extra:: * ;
87
+ import libc:: funcs:: extra:: kernel32:: * ;
88
+ import win32:: * ;
89
+ as_utf16_p ( n) { |u|
90
+ fill_utf16_buf_and_decode ( ) { |buf, sz|
91
+ GetEnvironmentVariableW ( u, buf, sz)
92
+ }
93
+ }
94
+ }
95
+
96
+
97
+ #[ cfg( target_os = "linux" ) ]
98
+ #[ cfg( target_os = "macos" ) ]
99
+ #[ cfg( target_os = "freebsd" ) ]
100
+ fn setenv ( n : str , v : str ) {
101
+
102
+ // FIXME: remove this when export globs work properly.
103
+ import libc:: funcs:: posix01:: unistd:: setenv;
104
+ str:: as_c_str ( n) { |nbuf|
105
+ str:: as_c_str ( v) { |vbuf|
106
+ setenv ( nbuf, vbuf, 1i32 ) ;
107
+ }
108
+ }
109
+ }
110
+
111
+
112
+ #[ cfg( target_os = "win32" ) ]
113
+ fn setenv ( n : str , v : str ) {
114
+ // FIXME: remove imports when export globs work properly.
115
+ import libc:: funcs:: extra:: kernel32:: * ;
116
+ import win32:: * ;
117
+ as_utf16_p ( n) { |nbuf|
118
+ as_utf16_p ( v) { |vbuf|
119
+ SetEnvironmentVariableW ( nbuf, vbuf) ;
120
+ }
121
+ }
122
+ }
123
+
124
+ }
0 commit comments