From cc7ae32ba1e3ef966cdf11c8d5a28c208215a1ea Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 17 Jul 2011 17:11:40 -0700 Subject: [PATCH] Add setenv to standard library --- src/lib/generic_os.rs | 48 +++++++++++++++++++++++++++++++++++- src/lib/win32_os.rs | 6 ++++- src/test/run-pass/lib-os.rs | 49 +++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/lib-os.rs diff --git a/src/lib/generic_os.rs b/src/lib/generic_os.rs index 0fb8d79378f..404ada3bc69 100644 --- a/src/lib/generic_os.rs +++ b/src/lib/generic_os.rs @@ -1,8 +1,54 @@ +import str::sbuf; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] fn getenv(str n) -> option::t[str] { auto s = os::libc::getenv(str::buf(n)); ret if (s as int == 0) { option::none[str] } else { option::some[str](str::str_from_cstr(s)) }; -} \ No newline at end of file +} + +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +fn setenv(str n, str v) { + auto nbuf = str::buf(n); + auto vbuf = str::buf(v); + os::libc::setenv(nbuf, vbuf, 1); +} + +#[cfg(target_os = "win32")] +fn getenv(str n) -> option::t[str]{ + auto nbuf = str::buf(n); + auto nsize = 256u; + while (true) { + auto vstr = str::alloc(nsize - 1u); + auto vbuf = str::buf(vstr); + auto res = os::kernel32::GetEnvironmentVariableA(nbuf, vbuf, nsize); + if (res == 0u) { + ret option::none; + } else if (res < nsize) { + ret option::some(str::str_from_cstr(vbuf)); + } else { + nsize = res; + } + } + fail; +} + +#[cfg(target_os = "win32")] +fn setenv(str n, str v) { + auto nbuf = str::buf(n); + auto vbuf = str::buf(v); + os::kernel32::SetEnvironmentVariableA(nbuf, vbuf); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs index 25ad71cecab..5370ce0dc5f 100644 --- a/src/lib/win32_os.rs +++ b/src/lib/win32_os.rs @@ -18,7 +18,6 @@ native "cdecl" mod libc = "" { fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint; fn fseek(FILE f, int offset, int whence) -> int; fn ftell(FILE f) -> int; - fn getenv(sbuf n) -> sbuf; fn _pipe(*mutable int fds, uint size, int mode) -> int; } @@ -49,6 +48,11 @@ mod libc_constants { } } +native "x86stdcall" mod kernel32 { + fn GetEnvironmentVariableA(sbuf n, sbuf v, uint nsize) -> uint; + fn SetEnvironmentVariableA(sbuf n, sbuf v) -> int; +} + fn exec_suffix() -> str { ret ".exe"; } fn target_os() -> str { ret "win32"; } diff --git a/src/test/run-pass/lib-os.rs b/src/test/run-pass/lib-os.rs new file mode 100644 index 00000000000..c3dc3e08dad --- /dev/null +++ b/src/test/run-pass/lib-os.rs @@ -0,0 +1,49 @@ +// xfail-stage0 + +use std; + +import std::generic_os::setenv; +import std::generic_os::getenv; +import std::option; + +#[test] +fn test_setenv() { + setenv("NAME", "VALUE"); + assert getenv("NAME") == option::some("VALUE"); +} + +#[test] +fn test_setenv_overwrite() { + setenv("NAME", "1"); + setenv("NAME", "2"); + assert getenv("NAME") == option::some("2"); +} + +// Windows GetEnvironmentVariable requires some extra work to make sure +// the buffer the variable is copied into is the right size +#[test] +fn test_getenv_big() { + auto s = ""; + auto i = 0; + while (i < 100) { + s += "aaaaaaaaaa"; + i += 1; + } + setenv("NAME", s); + assert getenv("NAME") == option::some(s); +} + +fn main() { + test_setenv(); + test_setenv_overwrite(); + test_getenv_big(); +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: