Skip to content

Commit 2aaf351

Browse files
authored
Port environment variables to use wasip2 methods (#610)
1 parent 08799da commit 2aaf351

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

libc-bottom-half/sources/__wasilibc_initialize_environ.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
#include <unistd.h>
22
#include <stdlib.h>
33
#include <sysexits.h>
4+
#ifdef __wasilibc_use_wasip2
5+
#include <wasi/wasip2.h>
6+
#else
47
#include <wasi/api.h>
8+
#endif
59
#include <wasi/libc.h>
610
#include <wasi/libc-environ.h>
711

@@ -26,6 +30,55 @@ static char *empty_environ[1] = { NULL };
2630

2731
// See the comments in libc-environ.h.
2832
void __wasilibc_initialize_environ(void) {
33+
#ifdef __wasilibc_use_wasip2
34+
// Get the environment
35+
wasip2_list_tuple2_string_string_t wasi_environment;
36+
environment_get_environment(&wasi_environment);
37+
38+
size_t environ_count = wasi_environment.len;
39+
if (environ_count == 0) {
40+
__wasilibc_environ = empty_environ;
41+
return;
42+
}
43+
44+
// Add 1 for the NULL pointer to mark the end, and check for overflow.
45+
size_t num_ptrs = environ_count + 1;
46+
if (num_ptrs == 0) {
47+
goto software;
48+
}
49+
50+
// Allocate memory for the array of pointers. This uses `calloc` both to
51+
// handle overflow and to initialize the NULL pointer at the end.
52+
char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
53+
54+
// Copy the environment variables
55+
for (size_t i = 0; i < environ_count; i++) {
56+
wasip2_tuple2_string_string_t pair = wasi_environment.ptr[i];
57+
// 1 extra character for the null terminator, 1 for the '=' character
58+
environ_ptrs[i] = malloc(pair.f0.len + pair.f1.len + 2);
59+
if (!environ_ptrs[i]) {
60+
for (size_t j = 0; j < i; j++)
61+
free(environ_ptrs[j]);
62+
free(environ_ptrs);
63+
goto software;
64+
}
65+
memcpy(environ_ptrs[i], pair.f0.ptr, pair.f0.len);
66+
environ_ptrs[i][pair.f0.len] = '=';
67+
memcpy(environ_ptrs[i] + pair.f0.len + 1, pair.f1.ptr, pair.f1.len);
68+
environ_ptrs[i][pair.f0.len + pair.f1.len + 1] = '\0';
69+
}
70+
71+
// Free the WASI environment list
72+
wasip2_list_tuple2_string_string_free(&wasi_environment);
73+
74+
// Initialize the environment from the created array
75+
__wasilibc_environ = environ_ptrs;
76+
return;
77+
software:
78+
wasip2_list_tuple2_string_string_free(&wasi_environment);
79+
_Exit(EX_SOFTWARE);
80+
81+
#else
2982
// Get the sizes of the arrays we'll have to create to copy in the environment.
3083
size_t environ_count;
3184
size_t environ_buf_size;
@@ -74,6 +127,7 @@ void __wasilibc_initialize_environ(void) {
74127
_Exit(EX_OSERR);
75128
software:
76129
_Exit(EX_SOFTWARE);
130+
#endif
77131
}
78132

79133
// See the comments in libc-environ.h.

test/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,10 @@ wasm_to_c = $(patsubst $(OBJPAT),$(SRCDIR)/%.c,$1)
210210
$(RUNDIR)/%/success: $(OBJPAT)
211211
@mkdir -p $(@D)
212212
@DIR="$(abspath $(@D))" \
213+
ENV="$(shell scripts/add-flags.py ENV $(call wasm_to_c,$<))" \
213214
WASM="$(abspath $<)" \
214-
ENGINE="$(ENGINE) $(shell scripts/add-flags.py RUN $(call wasm_to_c,$<))" \
215+
ENGINE="$(ENGINE)" \
216+
RUN="$(shell scripts/add-flags.py RUN $(call wasm_to_c,$<))" \
215217
ARGS="$(shell scripts/add-flags.py ARGS $(call wasm_to_c,$<))" \
216218
scripts/run-test.sh
217219

test/scripts/browser-test/harness.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const SKIP_TESTS = [
2626
"libc-test/functional/pthread_tsd",
2727
// Skip test that uses command-line arguments
2828
"misc/argv_two_args",
29+
// Skip test that uses environment variables
30+
"misc/external_env",
2931
// XFAIL: @bjorn3/browser_wasi_shim doesn't support symlinks for now
3032
"misc/fts",
3133
];

test/scripts/run-test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
# - a `fs` directory which the test may have used for file IO
77
# - an `output.log` file containing the output of the test
88
#
9-
# Usage: DIR=... WASM=... ENGINE=... ARGS="..." ./run-test.sh
9+
# Usage: ENV="..." DIR=... WASM=... ENGINE=... RUN="..." ARGS="..." ./run-test.sh
1010

1111
ENGINE="${ENGINE:-wasmtime}"
1212
[ -n "$WASM" ] || (echo "missing WASM variable" && exit 1)
1313
[ -n "$DIR" ] || (echo "missing DIR variable" && exit 1)
1414

1515
cd $DIR
1616
mkdir -p fs
17-
echo "$ENGINE $WASM $ARGS" > cmd.sh
17+
echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh
1818
chmod +x cmd.sh
1919
./cmd.sh &> output.log
2020
[ $? -eq 0 ] || echo "Test failed" >> output.log

test/src/misc/external_env.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! add-flags.py(CFLAGS): -I.
2+
//! add-flags.py(RUN): --wasi=inherit-env=y
3+
//! add-flags.py(ENV): VAR1=foo VAR2=bar
4+
#include <stdio.h>
5+
#include <string.h>
6+
#include <stdlib.h>
7+
#include "test.h"
8+
9+
#define TEST(c, ...) \
10+
( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )
11+
12+
int main(int argc, char **argv)
13+
{
14+
char* s = getenv("VAR1");
15+
TEST(strcmp(s, "foo")==0);
16+
s = getenv("VAR2");
17+
TEST(strcmp(s, "bar")==0);
18+
19+
return t_status;
20+
}

0 commit comments

Comments
 (0)