]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
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 | //! Implementation of `std::os` functionality for unix systems | |
12 | ||
c34b1796 AL |
13 | #![allow(unused_imports)] // lots of cfg code here |
14 | ||
1a4d82fc | 15 | use prelude::v1::*; |
c34b1796 | 16 | use os::unix::prelude::*; |
1a4d82fc | 17 | |
85aaf69f | 18 | use error::Error as StdError; |
c34b1796 | 19 | use ffi::{CString, CStr, OsString, OsStr}; |
1a4d82fc | 20 | use fmt; |
c34b1796 | 21 | use io; |
85aaf69f | 22 | use iter; |
1a4d82fc | 23 | use libc::{self, c_int, c_char, c_void}; |
85aaf69f | 24 | use mem; |
1a4d82fc | 25 | use ptr; |
c34b1796 | 26 | use path::{self, PathBuf}; |
85aaf69f | 27 | use slice; |
1a4d82fc | 28 | use str; |
85aaf69f SL |
29 | use sys::c; |
30 | use sys::fd; | |
85aaf69f | 31 | use vec; |
1a4d82fc | 32 | |
85aaf69f SL |
33 | const BUF_BYTES: usize = 2048; |
34 | const TMPBUF_SZ: usize = 128; | |
1a4d82fc | 35 | |
c34b1796 AL |
36 | fn bytes2path(b: &[u8]) -> PathBuf { |
37 | PathBuf::from(<OsStr as OsStrExt>::from_bytes(b)) | |
38 | } | |
39 | ||
40 | fn os2path(os: OsString) -> PathBuf { | |
41 | bytes2path(os.as_bytes()) | |
42 | } | |
43 | ||
1a4d82fc | 44 | /// Returns the platform-specific value of errno |
85aaf69f | 45 | pub fn errno() -> i32 { |
1a4d82fc JJ |
46 | #[cfg(any(target_os = "macos", |
47 | target_os = "ios", | |
48 | target_os = "freebsd"))] | |
85aaf69f SL |
49 | unsafe fn errno_location() -> *const c_int { |
50 | extern { fn __error() -> *const c_int; } | |
51 | __error() | |
1a4d82fc JJ |
52 | } |
53 | ||
c34b1796 AL |
54 | #[cfg(target_os = "bitrig")] |
55 | fn errno_location() -> *const c_int { | |
56 | extern { | |
57 | fn __errno() -> *const c_int; | |
58 | } | |
59 | unsafe { | |
60 | __errno() | |
61 | } | |
62 | } | |
63 | ||
1a4d82fc | 64 | #[cfg(target_os = "dragonfly")] |
85aaf69f SL |
65 | unsafe fn errno_location() -> *const c_int { |
66 | extern { fn __dfly_error() -> *const c_int; } | |
67 | __dfly_error() | |
68 | } | |
69 | ||
70 | #[cfg(target_os = "openbsd")] | |
71 | unsafe fn errno_location() -> *const c_int { | |
72 | extern { fn __errno() -> *const c_int; } | |
73 | __errno() | |
1a4d82fc JJ |
74 | } |
75 | ||
76 | #[cfg(any(target_os = "linux", target_os = "android"))] | |
85aaf69f SL |
77 | unsafe fn errno_location() -> *const c_int { |
78 | extern { fn __errno_location() -> *const c_int; } | |
79 | __errno_location() | |
1a4d82fc JJ |
80 | } |
81 | ||
82 | unsafe { | |
85aaf69f | 83 | (*errno_location()) as i32 |
1a4d82fc JJ |
84 | } |
85 | } | |
86 | ||
9346a6ac | 87 | /// Gets a detailed string description for the given error number. |
1a4d82fc | 88 | pub fn error_string(errno: i32) -> String { |
1a4d82fc | 89 | #[cfg(target_os = "linux")] |
85aaf69f SL |
90 | extern { |
91 | #[link_name = "__xpg_strerror_r"] | |
92 | fn strerror_r(errnum: c_int, buf: *mut c_char, | |
93 | buflen: libc::size_t) -> c_int; | |
94 | } | |
95 | #[cfg(not(target_os = "linux"))] | |
96 | extern { | |
97 | fn strerror_r(errnum: c_int, buf: *mut c_char, | |
98 | buflen: libc::size_t) -> c_int; | |
1a4d82fc JJ |
99 | } |
100 | ||
101 | let mut buf = [0 as c_char; TMPBUF_SZ]; | |
102 | ||
103 | let p = buf.as_mut_ptr(); | |
104 | unsafe { | |
105 | if strerror_r(errno as c_int, p, buf.len() as libc::size_t) < 0 { | |
106 | panic!("strerror_r failure"); | |
107 | } | |
108 | ||
109 | let p = p as *const _; | |
85aaf69f | 110 | str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string() |
1a4d82fc JJ |
111 | } |
112 | } | |
113 | ||
c34b1796 | 114 | pub fn getcwd() -> io::Result<PathBuf> { |
1a4d82fc JJ |
115 | let mut buf = [0 as c_char; BUF_BYTES]; |
116 | unsafe { | |
117 | if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { | |
c34b1796 | 118 | Err(io::Error::last_os_error()) |
1a4d82fc | 119 | } else { |
c34b1796 | 120 | Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes())) |
1a4d82fc JJ |
121 | } |
122 | } | |
123 | } | |
124 | ||
c34b1796 AL |
125 | pub fn chdir(p: &path::Path) -> io::Result<()> { |
126 | let p: &OsStr = p.as_ref(); | |
127 | let p = try!(CString::new(p.as_bytes())); | |
85aaf69f SL |
128 | unsafe { |
129 | match libc::chdir(p.as_ptr()) == (0 as c_int) { | |
130 | true => Ok(()), | |
c34b1796 | 131 | false => Err(io::Error::last_os_error()), |
85aaf69f | 132 | } |
1a4d82fc | 133 | } |
85aaf69f SL |
134 | } |
135 | ||
136 | pub struct SplitPaths<'a> { | |
137 | iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, | |
c34b1796 | 138 | fn(&'a [u8]) -> PathBuf>, |
85aaf69f SL |
139 | } |
140 | ||
141 | pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { | |
142 | fn is_colon(b: &u8) -> bool { *b == b':' } | |
143 | let unparsed = unparsed.as_bytes(); | |
144 | SplitPaths { | |
145 | iter: unparsed.split(is_colon as fn(&u8) -> bool) | |
c34b1796 | 146 | .map(bytes2path as fn(&'a [u8]) -> PathBuf) |
1a4d82fc | 147 | } |
1a4d82fc JJ |
148 | } |
149 | ||
85aaf69f | 150 | impl<'a> Iterator for SplitPaths<'a> { |
c34b1796 AL |
151 | type Item = PathBuf; |
152 | fn next(&mut self) -> Option<PathBuf> { self.iter.next() } | |
85aaf69f | 153 | fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } |
1a4d82fc JJ |
154 | } |
155 | ||
85aaf69f SL |
156 | #[derive(Debug)] |
157 | pub struct JoinPathsError; | |
158 | ||
159 | pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError> | |
c34b1796 | 160 | where I: Iterator<Item=T>, T: AsRef<OsStr> |
85aaf69f | 161 | { |
1a4d82fc JJ |
162 | let mut joined = Vec::new(); |
163 | let sep = b':'; | |
164 | ||
85aaf69f | 165 | for (i, path) in paths.enumerate() { |
c34b1796 | 166 | let path = path.as_ref().as_bytes(); |
1a4d82fc | 167 | if i > 0 { joined.push(sep) } |
85aaf69f SL |
168 | if path.contains(&sep) { |
169 | return Err(JoinPathsError) | |
170 | } | |
1a4d82fc JJ |
171 | joined.push_all(path); |
172 | } | |
85aaf69f SL |
173 | Ok(OsStringExt::from_vec(joined)) |
174 | } | |
1a4d82fc | 175 | |
85aaf69f SL |
176 | impl fmt::Display for JoinPathsError { |
177 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
178 | "path segment contains separator `:`".fmt(f) | |
179 | } | |
180 | } | |
181 | ||
182 | impl StdError for JoinPathsError { | |
183 | fn description(&self) -> &str { "failed to join paths" } | |
1a4d82fc JJ |
184 | } |
185 | ||
186 | #[cfg(target_os = "freebsd")] | |
c34b1796 | 187 | pub fn current_exe() -> io::Result<PathBuf> { |
1a4d82fc JJ |
188 | unsafe { |
189 | use libc::funcs::bsd44::*; | |
190 | use libc::consts::os::extra::*; | |
191 | let mut mib = vec![CTL_KERN as c_int, | |
192 | KERN_PROC as c_int, | |
193 | KERN_PROC_PATHNAME as c_int, | |
194 | -1 as c_int]; | |
195 | let mut sz: libc::size_t = 0; | |
196 | let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, | |
197 | ptr::null_mut(), &mut sz, ptr::null_mut(), | |
85aaf69f | 198 | 0 as libc::size_t); |
c34b1796 AL |
199 | if err != 0 { return Err(io::Error::last_os_error()); } |
200 | if sz == 0 { return Err(io::Error::last_os_error()); } | |
201 | let mut v: Vec<u8> = Vec::with_capacity(sz as usize); | |
1a4d82fc JJ |
202 | let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, |
203 | v.as_mut_ptr() as *mut libc::c_void, &mut sz, | |
85aaf69f | 204 | ptr::null_mut(), 0 as libc::size_t); |
c34b1796 AL |
205 | if err != 0 { return Err(io::Error::last_os_error()); } |
206 | if sz == 0 { return Err(io::Error::last_os_error()); } | |
207 | v.set_len(sz as usize - 1); // chop off trailing NUL | |
208 | Ok(PathBuf::from(OsString::from_vec(v))) | |
1a4d82fc JJ |
209 | } |
210 | } | |
211 | ||
212 | #[cfg(target_os = "dragonfly")] | |
c34b1796 AL |
213 | pub fn current_exe() -> io::Result<PathBuf> { |
214 | ::fs::read_link("/proc/curproc/file") | |
85aaf69f SL |
215 | } |
216 | ||
c34b1796 AL |
217 | #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] |
218 | pub fn current_exe() -> io::Result<PathBuf> { | |
62682a34 SL |
219 | use sync::StaticMutex; |
220 | static LOCK: StaticMutex = StaticMutex::new(); | |
85aaf69f SL |
221 | |
222 | extern { | |
223 | fn rust_current_exe() -> *const c_char; | |
1a4d82fc | 224 | } |
1a4d82fc | 225 | |
85aaf69f | 226 | let _guard = LOCK.lock(); |
1a4d82fc | 227 | |
85aaf69f SL |
228 | unsafe { |
229 | let v = rust_current_exe(); | |
230 | if v.is_null() { | |
c34b1796 | 231 | Err(io::Error::last_os_error()) |
85aaf69f | 232 | } else { |
c34b1796 AL |
233 | let vec = CStr::from_ptr(v).to_bytes().to_vec(); |
234 | Ok(PathBuf::from(OsString::from_vec(vec))) | |
85aaf69f | 235 | } |
1a4d82fc JJ |
236 | } |
237 | } | |
238 | ||
85aaf69f | 239 | #[cfg(any(target_os = "linux", target_os = "android"))] |
c34b1796 AL |
240 | pub fn current_exe() -> io::Result<PathBuf> { |
241 | ::fs::read_link("/proc/self/exe") | |
85aaf69f SL |
242 | } |
243 | ||
1a4d82fc | 244 | #[cfg(any(target_os = "macos", target_os = "ios"))] |
c34b1796 | 245 | pub fn current_exe() -> io::Result<PathBuf> { |
1a4d82fc JJ |
246 | unsafe { |
247 | use libc::funcs::extra::_NSGetExecutablePath; | |
248 | let mut sz: u32 = 0; | |
249 | _NSGetExecutablePath(ptr::null_mut(), &mut sz); | |
c34b1796 AL |
250 | if sz == 0 { return Err(io::Error::last_os_error()); } |
251 | let mut v: Vec<u8> = Vec::with_capacity(sz as usize); | |
1a4d82fc | 252 | let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); |
c34b1796 AL |
253 | if err != 0 { return Err(io::Error::last_os_error()); } |
254 | v.set_len(sz as usize - 1); // chop off trailing NUL | |
255 | Ok(PathBuf::from(OsString::from_vec(v))) | |
1a4d82fc JJ |
256 | } |
257 | } | |
258 | ||
85aaf69f SL |
259 | pub struct Args { |
260 | iter: vec::IntoIter<OsString>, | |
261 | _dont_send_or_sync_me: *mut (), | |
262 | } | |
263 | ||
264 | impl Iterator for Args { | |
265 | type Item = OsString; | |
266 | fn next(&mut self) -> Option<OsString> { self.iter.next() } | |
267 | fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } | |
268 | } | |
269 | ||
270 | impl ExactSizeIterator for Args { | |
271 | fn len(&self) -> usize { self.iter.len() } | |
272 | } | |
273 | ||
274 | /// Returns the command line arguments | |
275 | /// | |
276 | /// Returns a list of the command line arguments. | |
277 | #[cfg(target_os = "macos")] | |
278 | pub fn args() -> Args { | |
279 | extern { | |
280 | // These functions are in crt_externs.h. | |
281 | fn _NSGetArgc() -> *mut c_int; | |
282 | fn _NSGetArgv() -> *mut *mut *mut c_char; | |
283 | } | |
284 | ||
285 | let vec = unsafe { | |
286 | let (argc, argv) = (*_NSGetArgc() as isize, | |
287 | *_NSGetArgv() as *const *const c_char); | |
c34b1796 | 288 | (0.. argc as isize).map(|i| { |
85aaf69f SL |
289 | let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec(); |
290 | OsStringExt::from_vec(bytes) | |
291 | }).collect::<Vec<_>>() | |
292 | }; | |
293 | Args { | |
294 | iter: vec.into_iter(), | |
295 | _dont_send_or_sync_me: 0 as *mut (), | |
296 | } | |
297 | } | |
298 | ||
299 | // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs | |
300 | // and use underscores in their names - they're most probably | |
301 | // are considered private and therefore should be avoided | |
302 | // Here is another way to get arguments using Objective C | |
303 | // runtime | |
304 | // | |
305 | // In general it looks like: | |
306 | // res = Vec::new() | |
307 | // let args = [[NSProcessInfo processInfo] arguments] | |
c34b1796 | 308 | // for i in (0..[args count]) |
85aaf69f SL |
309 | // res.push([args objectAtIndex:i]) |
310 | // res | |
311 | #[cfg(target_os = "ios")] | |
312 | pub fn args() -> Args { | |
85aaf69f SL |
313 | use mem; |
314 | ||
315 | #[link(name = "objc")] | |
316 | extern { | |
317 | fn sel_registerName(name: *const libc::c_uchar) -> Sel; | |
318 | fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; | |
319 | fn objc_getClass(class_name: *const libc::c_uchar) -> NsId; | |
320 | } | |
321 | ||
322 | #[link(name = "Foundation", kind = "framework")] | |
323 | extern {} | |
324 | ||
325 | type Sel = *const libc::c_void; | |
326 | type NsId = *const libc::c_void; | |
327 | ||
328 | let mut res = Vec::new(); | |
329 | ||
1a4d82fc | 330 | unsafe { |
85aaf69f SL |
331 | let process_info_sel = sel_registerName("processInfo\0".as_ptr()); |
332 | let arguments_sel = sel_registerName("arguments\0".as_ptr()); | |
333 | let utf8_sel = sel_registerName("UTF8String\0".as_ptr()); | |
334 | let count_sel = sel_registerName("count\0".as_ptr()); | |
335 | let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr()); | |
336 | ||
337 | let klass = objc_getClass("NSProcessInfo\0".as_ptr()); | |
338 | let info = objc_msgSend(klass, process_info_sel); | |
339 | let args = objc_msgSend(info, arguments_sel); | |
340 | ||
c34b1796 AL |
341 | let cnt: usize = mem::transmute(objc_msgSend(args, count_sel)); |
342 | for i in (0..cnt) { | |
85aaf69f SL |
343 | let tmp = objc_msgSend(args, object_at_sel, i); |
344 | let utf_c_str: *const libc::c_char = | |
345 | mem::transmute(objc_msgSend(tmp, utf8_sel)); | |
346 | let bytes = CStr::from_ptr(utf_c_str).to_bytes(); | |
c34b1796 | 347 | res.push(OsString::from(str::from_utf8(bytes).unwrap())) |
1a4d82fc JJ |
348 | } |
349 | } | |
85aaf69f SL |
350 | |
351 | Args { iter: res.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } | |
352 | } | |
353 | ||
354 | #[cfg(any(target_os = "linux", | |
355 | target_os = "android", | |
356 | target_os = "freebsd", | |
357 | target_os = "dragonfly", | |
c34b1796 | 358 | target_os = "bitrig", |
85aaf69f SL |
359 | target_os = "openbsd"))] |
360 | pub fn args() -> Args { | |
361 | use rt; | |
362 | let bytes = rt::args::clone().unwrap_or(Vec::new()); | |
363 | let v: Vec<OsString> = bytes.into_iter().map(|v| { | |
364 | OsStringExt::from_vec(v) | |
365 | }).collect(); | |
366 | Args { iter: v.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } | |
367 | } | |
368 | ||
369 | pub struct Env { | |
370 | iter: vec::IntoIter<(OsString, OsString)>, | |
371 | _dont_send_or_sync_me: *mut (), | |
372 | } | |
373 | ||
374 | impl Iterator for Env { | |
375 | type Item = (OsString, OsString); | |
376 | fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } | |
377 | fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } | |
378 | } | |
379 | ||
380 | #[cfg(target_os = "macos")] | |
381 | pub unsafe fn environ() -> *mut *const *const c_char { | |
382 | extern { fn _NSGetEnviron() -> *mut *const *const c_char; } | |
383 | _NSGetEnviron() | |
384 | } | |
385 | ||
386 | #[cfg(not(target_os = "macos"))] | |
387 | pub unsafe fn environ() -> *mut *const *const c_char { | |
388 | extern { static mut environ: *const *const c_char; } | |
389 | &mut environ | |
390 | } | |
391 | ||
392 | /// Returns a vector of (variable, value) byte-vector pairs for all the | |
393 | /// environment variables of the current process. | |
394 | pub fn env() -> Env { | |
395 | return unsafe { | |
396 | let mut environ = *environ(); | |
397 | if environ as usize == 0 { | |
398 | panic!("os::env() failure getting env string from OS: {}", | |
c34b1796 | 399 | io::Error::last_os_error()); |
85aaf69f SL |
400 | } |
401 | let mut result = Vec::new(); | |
402 | while *environ != ptr::null() { | |
403 | result.push(parse(CStr::from_ptr(*environ).to_bytes())); | |
404 | environ = environ.offset(1); | |
405 | } | |
406 | Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } | |
407 | }; | |
408 | ||
409 | fn parse(input: &[u8]) -> (OsString, OsString) { | |
c34b1796 | 410 | let mut it = input.splitn(2, |b| *b == b'='); |
85aaf69f SL |
411 | let key = it.next().unwrap().to_vec(); |
412 | let default: &[u8] = &[]; | |
413 | let val = it.next().unwrap_or(default).to_vec(); | |
414 | (OsStringExt::from_vec(key), OsStringExt::from_vec(val)) | |
415 | } | |
1a4d82fc JJ |
416 | } |
417 | ||
85aaf69f | 418 | pub fn getenv(k: &OsStr) -> Option<OsString> { |
1a4d82fc | 419 | unsafe { |
85aaf69f SL |
420 | let s = k.to_cstring().unwrap(); |
421 | let s = libc::getenv(s.as_ptr()) as *const _; | |
422 | if s.is_null() { | |
423 | None | |
424 | } else { | |
425 | Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) | |
426 | } | |
427 | } | |
428 | } | |
429 | ||
430 | pub fn setenv(k: &OsStr, v: &OsStr) { | |
431 | unsafe { | |
432 | let k = k.to_cstring().unwrap(); | |
433 | let v = v.to_cstring().unwrap(); | |
434 | if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { | |
c34b1796 | 435 | panic!("failed setenv: {}", io::Error::last_os_error()); |
85aaf69f SL |
436 | } |
437 | } | |
438 | } | |
439 | ||
440 | pub fn unsetenv(n: &OsStr) { | |
441 | unsafe { | |
442 | let nbuf = n.to_cstring().unwrap(); | |
443 | if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { | |
c34b1796 | 444 | panic!("failed unsetenv: {}", io::Error::last_os_error()); |
85aaf69f SL |
445 | } |
446 | } | |
447 | } | |
448 | ||
85aaf69f SL |
449 | pub fn page_size() -> usize { |
450 | unsafe { | |
451 | libc::sysconf(libc::_SC_PAGESIZE) as usize | |
452 | } | |
453 | } | |
454 | ||
c34b1796 AL |
455 | pub fn temp_dir() -> PathBuf { |
456 | getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| { | |
85aaf69f | 457 | if cfg!(target_os = "android") { |
c34b1796 | 458 | PathBuf::from("/data/local/tmp") |
85aaf69f | 459 | } else { |
c34b1796 | 460 | PathBuf::from("/tmp") |
85aaf69f SL |
461 | } |
462 | }) | |
463 | } | |
464 | ||
c34b1796 AL |
465 | pub fn home_dir() -> Option<PathBuf> { |
466 | return getenv("HOME".as_ref()).or_else(|| unsafe { | |
85aaf69f | 467 | fallback() |
c34b1796 | 468 | }).map(os2path); |
85aaf69f SL |
469 | |
470 | #[cfg(any(target_os = "android", | |
471 | target_os = "ios"))] | |
472 | unsafe fn fallback() -> Option<OsString> { None } | |
473 | #[cfg(not(any(target_os = "android", | |
474 | target_os = "ios")))] | |
475 | unsafe fn fallback() -> Option<OsString> { | |
c34b1796 | 476 | let amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { |
85aaf69f SL |
477 | n if n < 0 => 512 as usize, |
478 | n => n as usize, | |
479 | }; | |
480 | let me = libc::getuid(); | |
481 | loop { | |
482 | let mut buf = Vec::with_capacity(amt); | |
483 | let mut passwd: c::passwd = mem::zeroed(); | |
484 | let mut result = 0 as *mut _; | |
485 | match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), | |
486 | buf.capacity() as libc::size_t, | |
487 | &mut result) { | |
488 | 0 if !result.is_null() => {} | |
489 | _ => return None | |
490 | } | |
491 | let ptr = passwd.pw_dir as *const _; | |
492 | let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); | |
493 | return Some(OsStringExt::from_vec(bytes)) | |
494 | } | |
1a4d82fc JJ |
495 | } |
496 | } | |
c34b1796 AL |
497 | |
498 | pub fn exit(code: i32) -> ! { | |
499 | unsafe { libc::exit(code as c_int) } | |
500 | } |