]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/args.rs
Do not use entropy during gen_weighted_bool(1)
[rust.git] / src / libstd / rt / args.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Global storage for command line arguments
12 //!
13 //! The current incarnation of the Rust runtime expects for
14 //! the processes `argc` and `argv` arguments to be stored
15 //! in a globally-accessible location for use by the `os` module.
16 //!
17 //! Only valid to call on Linux. Mac and Windows use syscalls to
18 //! discover the command line arguments.
19 //!
20 //! FIXME #7756: Would be nice for this to not exist.
21
22 use core::prelude::*;
23 use vec::Vec;
24
25 /// One-time global initialization.
26 pub unsafe fn init(argc: int, argv: *const *const u8) { imp::init(argc, argv) }
27
28 /// One-time global cleanup.
29 pub unsafe fn cleanup() { imp::cleanup() }
30
31 /// Take the global arguments from global storage.
32 pub fn take() -> Option<Vec<Vec<u8>>> { imp::take() }
33
34 /// Give the global arguments to global storage.
35 ///
36 /// It is an error if the arguments already exist.
37 pub fn put(args: Vec<Vec<u8>>) { imp::put(args) }
38
39 /// Make a clone of the global arguments.
40 pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
41
42 #[cfg(any(target_os = "linux",
43           target_os = "android",
44           target_os = "freebsd",
45           target_os = "dragonfly"))]
46 mod imp {
47     use prelude::v1::*;
48
49     use mem;
50     use slice;
51
52     use sync::{StaticMutex, MUTEX_INIT};
53
54     static mut GLOBAL_ARGS_PTR: uint = 0;
55     static LOCK: StaticMutex = MUTEX_INIT;
56
57     pub unsafe fn init(argc: int, argv: *const *const u8) {
58         let args = load_argc_and_argv(argc, argv);
59         put(args);
60     }
61
62     pub unsafe fn cleanup() {
63         take();
64         LOCK.destroy();
65     }
66
67     pub fn take() -> Option<Vec<Vec<u8>>> {
68         let _guard = LOCK.lock();
69         unsafe {
70             let ptr = get_global_ptr();
71             let val = mem::replace(&mut *ptr, None);
72             val.as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
73         }
74     }
75
76     pub fn put(args: Vec<Vec<u8>>) {
77         let _guard = LOCK.lock();
78         unsafe {
79             let ptr = get_global_ptr();
80             rtassert!((*ptr).is_none());
81             (*ptr) = Some(box args.clone());
82         }
83     }
84
85     pub fn clone() -> Option<Vec<Vec<u8>>> {
86         let _guard = LOCK.lock();
87         unsafe {
88             let ptr = get_global_ptr();
89             (*ptr).as_ref().map(|s: &Box<Vec<Vec<u8>>>| (**s).clone())
90         }
91     }
92
93     fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
94         unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
95     }
96
97     unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
98         range(0, argc as uint).map(|i| {
99             let arg = *argv.offset(i as int);
100             let mut len = 0u;
101             while *arg.offset(len as int) != 0 {
102                 len += 1u;
103             }
104             slice::from_raw_buf(&arg, len).to_vec()
105         }).collect()
106     }
107
108     #[cfg(test)]
109     mod tests {
110         use prelude::v1::*;
111         use finally::Finally;
112
113         use super::*;
114
115         #[test]
116         fn smoke_test() {
117             // Preserve the actual global state.
118             let saved_value = take();
119
120             let expected = vec![
121                 b"happy".to_vec(),
122                 b"today?".to_vec(),
123             ];
124
125             put(expected.clone());
126             assert!(clone() == Some(expected.clone()));
127             assert!(take() == Some(expected.clone()));
128             assert!(take() == None);
129
130             (|&mut:| {
131             }).finally(|| {
132                 // Restore the actual global state.
133                 match saved_value {
134                     Some(ref args) => put(args.clone()),
135                     None => ()
136                 }
137             })
138         }
139     }
140 }
141
142 #[cfg(any(target_os = "macos",
143           target_os = "ios",
144           target_os = "windows"))]
145 mod imp {
146     use core::prelude::*;
147     use vec::Vec;
148
149     pub unsafe fn init(_argc: int, _argv: *const *const u8) {
150     }
151
152     pub fn cleanup() {
153     }
154
155     pub fn take() -> Option<Vec<Vec<u8>>> {
156         panic!()
157     }
158
159     pub fn put(_args: Vec<Vec<u8>>) {
160         panic!()
161     }
162
163     pub fn clone() -> Option<Vec<Vec<u8>>> {
164         panic!()
165     }
166 }