]> git.proxmox.com Git - wasi-libc.git/blob - libc-bottom-half/sources/__environ.c
Fix environment variable init to exit successfully. (#159)
[wasi-libc.git] / libc-bottom-half / sources / __environ.c
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <sysexits.h>
4 #include <wasi/api.h>
5 #include <wasi/libc.h>
6
7 static char *empty_environ[1] = { NULL };
8 char **__environ = empty_environ;
9 extern __typeof(__environ) _environ __attribute__((weak, alias("__environ")));
10 extern __typeof(__environ) environ __attribute__((weak, alias("__environ")));
11
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) {
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);
25 if (err != __WASI_ERRNO_SUCCESS) {
26 goto oserr;
27 }
28 if (environ_count == 0) {
29 return;
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) {
35 goto software;
36 }
37
38 // Allocate memory for storing the environment chars.
39 char *environ_buf = malloc(environ_buf_size);
40 if (environ_buf == NULL) {
41 goto software;
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);
49 goto software;
50 }
51
52 // Fill the environment chars, and the __environ array with pointers into those chars.
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);
55 if (err != __WASI_ERRNO_SUCCESS) {
56 free(environ_buf);
57 free(environ_ptrs);
58 goto oserr;
59 }
60
61 __environ = environ_ptrs;
62 return;
63 oserr:
64 _Exit(EX_OSERR);
65 software:
66 _Exit(EX_SOFTWARE);
67 }