Skip to content

Commit cc7ae32

Browse files
committed
Add setenv to standard library
1 parent c40d626 commit cc7ae32

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

src/lib/generic_os.rs

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,54 @@
1+
import str::sbuf;
12

23

4+
#[cfg(target_os = "linux")]
5+
#[cfg(target_os = "macos")]
36
fn getenv(str n) -> option::t[str] {
47
auto s = os::libc::getenv(str::buf(n));
58
ret if (s as int == 0) {
69
option::none[str]
710
} else { option::some[str](str::str_from_cstr(s)) };
8-
}
11+
}
12+
13+
#[cfg(target_os = "linux")]
14+
#[cfg(target_os = "macos")]
15+
fn setenv(str n, str v) {
16+
auto nbuf = str::buf(n);
17+
auto vbuf = str::buf(v);
18+
os::libc::setenv(nbuf, vbuf, 1);
19+
}
20+
21+
#[cfg(target_os = "win32")]
22+
fn getenv(str n) -> option::t[str]{
23+
auto nbuf = str::buf(n);
24+
auto nsize = 256u;
25+
while (true) {
26+
auto vstr = str::alloc(nsize - 1u);
27+
auto vbuf = str::buf(vstr);
28+
auto res = os::kernel32::GetEnvironmentVariableA(nbuf, vbuf, nsize);
29+
if (res == 0u) {
30+
ret option::none;
31+
} else if (res < nsize) {
32+
ret option::some(str::str_from_cstr(vbuf));
33+
} else {
34+
nsize = res;
35+
}
36+
}
37+
fail;
38+
}
39+
40+
#[cfg(target_os = "win32")]
41+
fn setenv(str n, str v) {
42+
auto nbuf = str::buf(n);
43+
auto vbuf = str::buf(v);
44+
os::kernel32::SetEnvironmentVariableA(nbuf, vbuf);
45+
}
46+
47+
// Local Variables:
48+
// mode: rust;
49+
// fill-column: 78;
50+
// indent-tabs-mode: nil
51+
// c-basic-offset: 4
52+
// buffer-file-coding-system: utf-8-unix
53+
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
54+
// End:

src/lib/win32_os.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ native "cdecl" mod libc = "" {
1818
fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
1919
fn fseek(FILE f, int offset, int whence) -> int;
2020
fn ftell(FILE f) -> int;
21-
fn getenv(sbuf n) -> sbuf;
2221
fn _pipe(*mutable int fds, uint size, int mode) -> int;
2322
}
2423

@@ -49,6 +48,11 @@ mod libc_constants {
4948
}
5049
}
5150

51+
native "x86stdcall" mod kernel32 {
52+
fn GetEnvironmentVariableA(sbuf n, sbuf v, uint nsize) -> uint;
53+
fn SetEnvironmentVariableA(sbuf n, sbuf v) -> int;
54+
}
55+
5256
fn exec_suffix() -> str { ret ".exe"; }
5357

5458
fn target_os() -> str { ret "win32"; }

src/test/run-pass/lib-os.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// xfail-stage0
2+
3+
use std;
4+
5+
import std::generic_os::setenv;
6+
import std::generic_os::getenv;
7+
import std::option;
8+
9+
#[test]
10+
fn test_setenv() {
11+
setenv("NAME", "VALUE");
12+
assert getenv("NAME") == option::some("VALUE");
13+
}
14+
15+
#[test]
16+
fn test_setenv_overwrite() {
17+
setenv("NAME", "1");
18+
setenv("NAME", "2");
19+
assert getenv("NAME") == option::some("2");
20+
}
21+
22+
// Windows GetEnvironmentVariable requires some extra work to make sure
23+
// the buffer the variable is copied into is the right size
24+
#[test]
25+
fn test_getenv_big() {
26+
auto s = "";
27+
auto i = 0;
28+
while (i < 100) {
29+
s += "aaaaaaaaaa";
30+
i += 1;
31+
}
32+
setenv("NAME", s);
33+
assert getenv("NAME") == option::some(s);
34+
}
35+
36+
fn main() {
37+
test_setenv();
38+
test_setenv_overwrite();
39+
test_getenv_big();
40+
}
41+
42+
// Local Variables:
43+
// mode: rust;
44+
// fill-column: 78;
45+
// indent-tabs-mode: nil
46+
// c-basic-offset: 4
47+
// buffer-file-coding-system: utf-8-unix
48+
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
49+
// End:

0 commit comments

Comments
 (0)