]>
Commit | Line | Data |
---|---|---|
bdfbb545 DG |
1 | #include <unistd.h> |
2 | #include <stdlib.h> | |
410c6607 | 3 | #include <sysexits.h> |
446cb3f1 | 4 | #include <wasi/api.h> |
bdfbb545 | 5 | #include <wasi/libc.h> |
bdfbb545 | 6 | |
a8a5dbcf DG |
7 | static char *empty_environ[1] = { NULL }; |
8 | char **__environ = empty_environ; | |
bdfbb545 DG |
9 | extern __typeof(__environ) _environ __attribute__((weak, alias("__environ"))); |
10 | extern __typeof(__environ) environ __attribute__((weak, alias("__environ"))); | |
11 | ||
410c6607 DG |
12 | // We define this function here in the same source file as __environ, so that |
13 | // this function is called in iff environment variable support is used. | |
14 | // Concerning the 50 -- levels up to 100 are reserved for the implementation, | |
15 | // so we an arbitrary number in the middle of the range to allow other | |
16 | // reserved things to go before or after. | |
17 | __attribute__((constructor(50))) | |
18 | static void __wasilibc_populate_environ(void) { | |
bdfbb545 DG |
19 | __wasi_errno_t err; |
20 | ||
21 | // Get the sizes of the arrays we'll have to create to copy in the environment. | |
22 | size_t environ_count; | |
23 | size_t environ_buf_size; | |
24 | err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size); | |
446cb3f1 | 25 | if (err != __WASI_ERRNO_SUCCESS) { |
410c6607 | 26 | goto oserr; |
bdfbb545 DG |
27 | } |
28 | if (environ_count == 0) { | |
410c6607 | 29 | return; |
bdfbb545 DG |
30 | } |
31 | ||
32 | // Add 1 for the NULL pointer to mark the end, and check for overflow. | |
33 | size_t num_ptrs = environ_count + 1; | |
34 | if (num_ptrs == 0) { | |
410c6607 | 35 | goto software; |
bdfbb545 DG |
36 | } |
37 | ||
38 | // Allocate memory for storing the environment chars. | |
39 | char *environ_buf = malloc(environ_buf_size); | |
40 | if (environ_buf == NULL) { | |
410c6607 | 41 | goto software; |
bdfbb545 DG |
42 | } |
43 | ||
44 | // Allocate memory for the array of pointers. This uses `calloc` both to | |
45 | // handle overflow and to initialize the NULL pointer at the end. | |
46 | char **environ_ptrs = calloc(num_ptrs, sizeof(char *)); | |
47 | if (environ_ptrs == NULL) { | |
48 | free(environ_buf); | |
410c6607 | 49 | goto software; |
bdfbb545 DG |
50 | } |
51 | ||
52 | // Fill the environment chars, and the __environ array with pointers into those chars. | |
446cb3f1 DG |
53 | // TODO: Remove the casts on `environ_ptrs` and `environ_buf` once the witx is updated with char8 support. |
54 | err = __wasi_environ_get((uint8_t **)environ_ptrs, (uint8_t *)environ_buf); | |
410c6607 | 55 | if (err != __WASI_ERRNO_SUCCESS) { |
bdfbb545 DG |
56 | free(environ_buf); |
57 | free(environ_ptrs); | |
410c6607 | 58 | goto oserr; |
bdfbb545 | 59 | } |
410c6607 DG |
60 | |
61 | __environ = environ_ptrs; | |
1fad3389 | 62 | return; |
410c6607 DG |
63 | oserr: |
64 | _Exit(EX_OSERR); | |
65 | software: | |
66 | _Exit(EX_SOFTWARE); | |
bdfbb545 | 67 | } |