1
1
use super :: unsupported;
2
+ use crate :: collections:: HashMap ;
2
3
use crate :: error:: Error as StdError ;
3
4
use crate :: ffi:: { OsStr , OsString } ;
4
5
use crate :: marker:: PhantomData ;
5
6
use crate :: os:: xous:: ffi:: Error as XousError ;
6
7
use crate :: path:: { self , PathBuf } ;
7
- use crate :: { fmt, io} ;
8
+ use crate :: sync:: atomic:: { AtomicPtr , AtomicUsize , Ordering } ;
9
+ use crate :: sync:: { Mutex , Once } ;
10
+ use crate :: { fmt, io, vec} ;
11
+
12
+ pub ( crate ) mod params;
13
+
14
+ static PARAMS_ADDRESS : AtomicPtr < u8 > = AtomicPtr :: new ( core:: ptr:: null_mut ( ) ) ;
8
15
9
16
#[ cfg( not( test) ) ]
10
17
#[ cfg( feature = "panic_unwind" ) ]
11
18
mod eh_unwinding {
12
- pub ( crate ) struct EhFrameFinder ( usize /* eh_frame */ ) ;
13
- pub ( crate ) static mut EH_FRAME_SETTINGS : EhFrameFinder = EhFrameFinder ( 0 ) ;
14
- impl EhFrameFinder {
15
- pub ( crate ) unsafe fn init ( & mut self , eh_frame : usize ) {
16
- unsafe {
17
- EH_FRAME_SETTINGS . 0 = eh_frame;
18
- }
19
- }
20
- }
19
+ pub ( crate ) struct EhFrameFinder ;
20
+ pub ( crate ) static mut EH_FRAME_ADDRESS : usize = 0 ;
21
+ pub ( crate ) static EH_FRAME_SETTINGS : EhFrameFinder = EhFrameFinder ;
22
+
21
23
unsafe impl unwind:: EhFrameFinder for EhFrameFinder {
22
24
fn find ( & self , _pc : usize ) -> Option < unwind:: FrameInfo > {
23
- Some ( unwind:: FrameInfo {
24
- text_base : None ,
25
- kind : unwind:: FrameInfoKind :: EhFrame ( self . 0 ) ,
26
- } )
25
+ if unsafe { EH_FRAME_ADDRESS == 0 } {
26
+ None
27
+ } else {
28
+ Some ( unwind:: FrameInfo {
29
+ text_base : None ,
30
+ kind : unwind:: FrameInfoKind :: EhFrame ( unsafe { EH_FRAME_ADDRESS } ) ,
31
+ } )
32
+ }
27
33
}
28
34
}
29
35
}
@@ -41,12 +47,21 @@ mod c_compat {
41
47
}
42
48
43
49
#[ no_mangle]
44
- pub extern "C" fn _start ( eh_frame : usize ) {
50
+ pub extern "C" fn _start ( eh_frame : usize , params_address : usize ) {
45
51
#[ cfg( feature = "panic_unwind" ) ]
46
- unsafe {
47
- super :: eh_unwinding:: EH_FRAME_SETTINGS . init ( eh_frame) ;
52
+ {
53
+ unsafe { super :: eh_unwinding:: EH_FRAME_ADDRESS = eh_frame } ;
48
54
unwind:: set_custom_eh_frame_finder ( & super :: eh_unwinding:: EH_FRAME_SETTINGS ) . ok ( ) ;
49
55
}
56
+
57
+ if params_address != 0 {
58
+ let params_address = crate :: ptr:: with_exposed_provenance_mut :: < u8 > ( params_address) ;
59
+ if unsafe {
60
+ super :: params:: ApplicationParameters :: new_from_ptr ( params_address) . is_some ( )
61
+ } {
62
+ super :: PARAMS_ADDRESS . store ( params_address, core:: sync:: atomic:: Ordering :: Relaxed ) ;
63
+ }
64
+ }
50
65
exit ( unsafe { main ( ) } ) ;
51
66
}
52
67
@@ -116,44 +131,103 @@ pub fn current_exe() -> io::Result<PathBuf> {
116
131
unsupported ( )
117
132
}
118
133
119
- pub struct Env ( !) ;
134
+ pub ( crate ) fn get_application_parameters ( ) -> Option < params:: ApplicationParameters > {
135
+ let params_address = PARAMS_ADDRESS . load ( Ordering :: Relaxed ) ;
136
+ unsafe { params:: ApplicationParameters :: new_from_ptr ( params_address) }
137
+ }
138
+
139
+ // ---------- Environment handling ---------- //
140
+ static ENV : AtomicUsize = AtomicUsize :: new ( 0 ) ;
141
+ static ENV_INIT : Once = Once :: new ( ) ;
142
+ type EnvStore = Mutex < HashMap < OsString , OsString > > ;
143
+
144
+ fn get_env_store ( ) -> & ' static EnvStore {
145
+ ENV_INIT . call_once ( || {
146
+ let env_store = EnvStore :: default ( ) ;
147
+ if let Some ( params) = get_application_parameters ( ) {
148
+ for param in params {
149
+ if let Ok ( envs) = params:: EnvironmentBlock :: try_from ( & param) {
150
+ let mut env_store = env_store. lock ( ) . unwrap ( ) ;
151
+ for env in envs {
152
+ env_store. insert ( env. key . into ( ) , env. value . into ( ) ) ;
153
+ }
154
+ break ;
155
+ }
156
+ }
157
+ }
158
+ ENV . store ( Box :: into_raw ( Box :: new ( env_store) ) as _ , Ordering :: Relaxed )
159
+ } ) ;
160
+ unsafe { & * core:: ptr:: with_exposed_provenance :: < EnvStore > ( ENV . load ( Ordering :: Relaxed ) ) }
161
+ }
162
+
163
+ pub struct Env {
164
+ iter : vec:: IntoIter < ( OsString , OsString ) > ,
165
+ }
166
+
167
+ // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
168
+ pub struct EnvStrDebug < ' a > {
169
+ slice : & ' a [ ( OsString , OsString ) ] ,
170
+ }
171
+
172
+ impl fmt:: Debug for EnvStrDebug < ' _ > {
173
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
174
+ let Self { slice } = self ;
175
+ f. debug_list ( )
176
+ . entries ( slice. iter ( ) . map ( |( a, b) | ( a. to_str ( ) . unwrap ( ) , b. to_str ( ) . unwrap ( ) ) ) )
177
+ . finish ( )
178
+ }
179
+ }
120
180
121
181
impl Env {
122
182
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
123
183
pub fn str_debug ( & self ) -> impl fmt:: Debug + ' _ {
124
- let Self ( inner ) = self ;
125
- match * inner { }
184
+ let Self { iter } = self ;
185
+ EnvStrDebug { slice : iter . as_slice ( ) }
126
186
}
127
187
}
128
188
129
189
impl fmt:: Debug for Env {
130
- fn fmt ( & self , _ : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
131
- let Self ( inner ) = self ;
132
- match * inner { }
190
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
191
+ let Self { iter } = self ;
192
+ f . debug_list ( ) . entries ( iter . as_slice ( ) ) . finish ( )
133
193
}
134
194
}
135
195
196
+ impl !Send for Env { }
197
+ impl !Sync for Env { }
198
+
136
199
impl Iterator for Env {
137
200
type Item = ( OsString , OsString ) ;
138
201
fn next ( & mut self ) -> Option < ( OsString , OsString ) > {
139
- self . 0
202
+ self . iter . next ( )
203
+ }
204
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
205
+ self . iter . size_hint ( )
140
206
}
141
207
}
142
208
143
209
pub fn env ( ) -> Env {
144
- panic ! ( "not supported on this platform" )
210
+ let clone_to_vec = |map : & HashMap < OsString , OsString > | -> Vec < _ > {
211
+ map. iter ( ) . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) ) . collect ( )
212
+ } ;
213
+
214
+ let iter = clone_to_vec ( & * get_env_store ( ) . lock ( ) . unwrap ( ) ) . into_iter ( ) ;
215
+ Env { iter }
145
216
}
146
217
147
- pub fn getenv ( _ : & OsStr ) -> Option < OsString > {
148
- None
218
+ pub fn getenv ( k : & OsStr ) -> Option < OsString > {
219
+ get_env_store ( ) . lock ( ) . unwrap ( ) . get ( k ) . cloned ( )
149
220
}
150
221
151
- pub unsafe fn setenv ( _: & OsStr , _: & OsStr ) -> io:: Result < ( ) > {
152
- Err ( io:: const_io_error!( io:: ErrorKind :: Unsupported , "cannot set env vars on this platform" ) )
222
+ pub unsafe fn setenv ( k : & OsStr , v : & OsStr ) -> io:: Result < ( ) > {
223
+ let ( k, v) = ( k. to_owned ( ) , v. to_owned ( ) ) ;
224
+ get_env_store ( ) . lock ( ) . unwrap ( ) . insert ( k, v) ;
225
+ Ok ( ( ) )
153
226
}
154
227
155
- pub unsafe fn unsetenv ( _: & OsStr ) -> io:: Result < ( ) > {
156
- Err ( io:: const_io_error!( io:: ErrorKind :: Unsupported , "cannot unset env vars on this platform" ) )
228
+ pub unsafe fn unsetenv ( k : & OsStr ) -> io:: Result < ( ) > {
229
+ get_env_store ( ) . lock ( ) . unwrap ( ) . remove ( k) ;
230
+ Ok ( ( ) )
157
231
}
158
232
159
233
pub fn temp_dir ( ) -> PathBuf {
0 commit comments