diff --git a/src/lib/generic_os.rs b/src/lib/generic_os.rs index 0fb8d79378f9..21c3dee5ef33 100644 --- a/src/lib/generic_os.rs +++ b/src/lib/generic_os.rs @@ -1,8 +1,53 @@ +#[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::rustrt::rust_GetEnvironmentVariable(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::rustrt::rust_SetEnvironmentVariable(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 25ad71cecab1..77cb2a9b9fdd 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; } @@ -67,6 +66,8 @@ fn fd_FILE(int fd) -> libc::FILE { ret libc::_fdopen(fd, str::buf("r")); } native "rust" mod rustrt { fn rust_process_wait(int handle) -> int; fn rust_getcwd() -> str; + fn rust_SetEnvironmentVariable(sbuf n, sbuf v) -> int; + fn rust_GetEnvironmentVariable(sbuf n, sbuf v, uint nsize) -> uint; } fn waitpid(int pid) -> int { ret rustrt::rust_process_wait(pid); } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index df7b1cfc6d3a..7e72b2e7ab6b 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -650,6 +650,20 @@ rust_ptr_eq(rust_task *task, type_desc *t, rust_box *a, rust_box *b) { return a == b; } +#if defined(__WIN32__) +extern "C" CDECL int32_t +rust_SetEnvironmentVariable(rust_task *task, + const char *name, const char *val) { + return SetEnvironmentVariable(name, val); +} + +extern "C" CDECL uint32_t +rust_GetEnvironmentVariable(rust_task *task, + const char *name, char *buf, uint32_t size) { + return GetEnvironmentVariable(name, buf, size); +} +#endif + #if defined(__WIN32__) extern "C" CDECL void get_time(rust_task *task, uint32_t *sec, uint32_t *usec) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index f762f4a9be3c..9c0557729bfc 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -35,6 +35,8 @@ rust_ptr_eq rust_run_program rust_start rust_getcwd +rust_SetEnvironmentVariable +rust_GetEnvironmentVariable size_of squareroot str_alloc diff --git a/src/test/run-pass/lib-os.rs b/src/test/run-pass/lib-os.rs new file mode 100644 index 000000000000..c3dc3e08dad1 --- /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: