1 use crate::std::ffi::{c_char, CStr, OsString};
2 use crate::std::fmt;
3 use crate::std::os::hermit::ffi::OsStringExt;
4 use crate::std::ptr;
5 use crate::std::sync::atomic::{
6 AtomicIsize, AtomicPtr,
7 Ordering::{Acquire, Relaxed, Release},
8 };
9 use crate::std::vec;
10
11 static ARGC: AtomicIsize = AtomicIsize::new(0);
12 static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
13
14 /// One-time global initialization.
init(argc: isize, argv: *const *const u8)15 pub unsafe fn init(argc: isize, argv: *const *const u8) {
16 ARGC.store(argc, Relaxed);
17 // Use release ordering here to broadcast writes by the OS.
18 ARGV.store(argv as *mut *const u8, Release);
19 }
20
21 /// Returns the command line arguments
args() -> Args22 pub fn args() -> Args {
23 // Synchronize with the store above.
24 let argv = ARGV.load(Acquire);
25 // If argv has not been initialized yet, do not return any arguments.
26 let argc = if argv.is_null() {
27 0
28 } else {
29 ARGC.load(Relaxed)
30 };
31 let args: Vec<OsString> = (0..argc)
32 .map(|i| unsafe {
33 let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
34 OsStringExt::from_vec(cstr.to_bytes().to_vec())
35 })
36 .collect();
37
38 Args {
39 iter: args.into_iter(),
40 }
41 }
42
43 pub struct Args {
44 iter: vec::IntoIter<OsString>,
45 }
46
47 impl fmt::Debug for Args {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 self.iter.as_slice().fmt(f)
50 }
51 }
52
53 impl !Send for Args {}
54 impl !Sync for Args {}
55
56 impl Iterator for Args {
57 type Item = OsString;
next(&mut self) -> Option<OsString>58 fn next(&mut self) -> Option<OsString> {
59 self.iter.next()
60 }
size_hint(&self) -> (usize, Option<usize>)61 fn size_hint(&self) -> (usize, Option<usize>) {
62 self.iter.size_hint()
63 }
64 }
65
66 impl ExactSizeIterator for Args {
len(&self) -> usize67 fn len(&self) -> usize {
68 self.iter.len()
69 }
70 }
71
72 impl DoubleEndedIterator for Args {
next_back(&mut self) -> Option<OsString>73 fn next_back(&mut self) -> Option<OsString> {
74 self.iter.next_back()
75 }
76 }
77