Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use str::from_utf8_lossy() for os::env() and friends
Parse the environment by default with from_utf8_lossy. Also provide
byte-vector equivalents (e.g. os::env_as_bytes()).

Unfortunately, setenv() can't have a byte-vector equivalent because of
Windows support, unless we want to define a setenv_bytes() that fails
under Windows for non-UTF8 (or non-UTF16).
  • Loading branch information
lilyball committed Feb 15, 2014
1 parent c73d5ce commit d22b164
Showing 1 changed file with 60 additions and 11 deletions.
71 changes: 60 additions & 11 deletions src/libstd/os.rs
Expand Up @@ -160,10 +160,23 @@ fn with_env_lock<T>(f: || -> T) -> T {

/// Returns a vector of (variable, value) pairs for all the environment
/// variables of the current process.
///
/// Invalid UTF-8 bytes are replaced with \uFFFD. See `str::from_utf8_lossy()`
/// for details.
pub fn env() -> ~[(~str,~str)] {
env_as_bytes().move_iter().map(|(k,v)| {
let k = str::from_utf8_lossy(k).into_owned();
let v = str::from_utf8_lossy(v).into_owned();
(k,v)
}).collect()
}

/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
pub fn env_as_bytes() -> ~[(~[u8],~[u8])] {
unsafe {
#[cfg(windows)]
unsafe fn get_env_pairs() -> ~[~str] {
unsafe fn get_env_pairs() -> ~[~[u8]] {
use c_str;
use str::StrSlice;

Expand All @@ -178,13 +191,15 @@ pub fn env() -> ~[(~str,~str)] {
}
let mut result = ~[];
c_str::from_c_multistring(ch as *c_char, None, |cstr| {
result.push(cstr.as_str().unwrap().to_owned());
result.push(cstr.as_bytes_no_nul().to_owned());
});
FreeEnvironmentStringsA(ch);
result
}
#[cfg(unix)]
unsafe fn get_env_pairs() -> ~[~str] {
unsafe fn get_env_pairs() -> ~[~[u8]] {
use c_str::CString;

extern {
fn rust_env_pairs() -> **c_char;
}
Expand All @@ -195,20 +210,19 @@ pub fn env() -> ~[(~str,~str)] {
}
let mut result = ~[];
ptr::array_each(environ, |e| {
let env_pair = str::raw::from_c_str(e);
debug!("get_env_pairs: {}", env_pair);
let env_pair = CString::new(e, false).as_bytes_no_nul().to_owned();
result.push(env_pair);
});
result
}

fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
fn env_convert(input: ~[~[u8]]) -> ~[(~[u8], ~[u8])] {
let mut pairs = ~[];
for p in input.iter() {
let vs: ~[&str] = p.splitn('=', 1).collect();
debug!("splitting: len: {}", vs.len());
assert_eq!(vs.len(), 2);
pairs.push((vs[0].to_owned(), vs[1].to_owned()));
let vs: ~[&[u8]] = p.splitn(1, |b| *b == '=' as u8).collect();
let key = vs[0].to_owned();
let val = (if vs.len() < 2 { ~[] } else { vs[1].to_owned() });
pairs.push((key, val));
}
pairs
}
Expand All @@ -222,14 +236,34 @@ pub fn env() -> ~[(~str,~str)] {
#[cfg(unix)]
/// Fetches the environment variable `n` from the current process, returning
/// None if the variable isn't set.
///
/// Any invalid UTF-8 bytes in the value are replaced by \uFFFD. See
/// `str::from_utf8_lossy()` for details.
///
/// # Failure
///
/// Fails if `n` has any interior NULs.
pub fn getenv(n: &str) -> Option<~str> {
getenv_as_bytes(n).map(|v| str::from_utf8_lossy(v).into_owned())
}

#[cfg(unix)]
/// Fetches the environment variable `n` byte vector from the current process,
/// returning None if the variable isn't set.
///
/// # Failure
///
/// Fails if `n` has any interior NULs.
pub fn getenv_as_bytes(n: &str) -> Option<~[u8]> {
use c_str::CString;

unsafe {
with_env_lock(|| {
let s = n.with_c_str(|buf| libc::getenv(buf));
if s.is_null() {
None
} else {
Some(str::raw::from_c_str(s))
Some(CString::new(s, false).as_bytes_no_nul().to_owned())
}
})
}
Expand All @@ -251,10 +285,21 @@ pub fn getenv(n: &str) -> Option<~str> {
}
}

#[cfg(windows)]
/// Fetches the environment variable `n` byte vector from the current process,
/// returning None if the variable isn't set.
pub fn getenv_as_bytes(n: &str) -> Option<~[u8]> {
getenv(n).map(|s| s.into_bytes())
}


#[cfg(unix)]
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
///
/// # Failure
///
/// Fails if `n` or `v` have any interior NULs.
pub fn setenv(n: &str, v: &str) {
unsafe {
with_env_lock(|| {
Expand Down Expand Up @@ -285,6 +330,10 @@ pub fn setenv(n: &str, v: &str) {
}

/// Remove a variable from the environment entirely
///
/// # Failure
///
/// Fails (on unix) if `n` has any interior NULs.
pub fn unsetenv(n: &str) {
#[cfg(unix)]
fn _unsetenv(n: &str) {
Expand Down

9 comments on commit d22b164

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from erickt
at lilyball@d22b164

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging kballard/rust/env-args-bytes = d22b164 into auto

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kballard/rust/env-args-bytes = d22b164 merged ok, testing candidate = 4c3cde60

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from erickt
at lilyball@d22b164

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging kballard/rust/env-args-bytes = d22b164 into auto

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kballard/rust/env-args-bytes = d22b164 merged ok, testing candidate = fba32ea

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on d22b164 Feb 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = fba32ea

Please sign in to comment.