]> git.proxmox.com Git - wasi-libc.git/blob - libc-bottom-half/sources/__environ.c
38c82d44bcb6d9a5edb3815b6830a1524c13d0f6
[wasi-libc.git] / libc-bottom-half / sources / __environ.c
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <wasi/api.h>
4 #include <wasi/libc.h>
5 #include <wasi/libc-internal.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 // This function is referenced by a weak symbol in crt1.c, and we define
13 // it here in the same source file as __environ, so that this function is
14 // linked in iff environment variable support is used.
15 __wasi_errno_t __wasilibc_populate_environ(void) {
16 __wasi_errno_t err;
17
18 // Get the sizes of the arrays we'll have to create to copy in the environment.
19 size_t environ_count;
20 size_t environ_buf_size;
21 err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size);
22 if (err != __WASI_ERRNO_SUCCESS) {
23 return err;
24 }
25 if (environ_count == 0) {
26 return __WASI_ERRNO_SUCCESS;
27 }
28
29 // Add 1 for the NULL pointer to mark the end, and check for overflow.
30 size_t num_ptrs = environ_count + 1;
31 if (num_ptrs == 0) {
32 return __WASI_ERRNO_NOMEM;
33 }
34
35 // Allocate memory for storing the environment chars.
36 char *environ_buf = malloc(environ_buf_size);
37 if (environ_buf == NULL) {
38 return __WASI_ERRNO_NOMEM;
39 }
40
41 // Allocate memory for the array of pointers. This uses `calloc` both to
42 // handle overflow and to initialize the NULL pointer at the end.
43 char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
44 if (environ_ptrs == NULL) {
45 free(environ_buf);
46 return __WASI_ERRNO_NOMEM;
47 }
48
49 // Fill the environment chars, and the __environ array with pointers into those chars.
50 // TODO: Remove the casts on `environ_ptrs` and `environ_buf` once the witx is updated with char8 support.
51 err = __wasi_environ_get((uint8_t **)environ_ptrs, (uint8_t *)environ_buf);
52 if (err == __WASI_ERRNO_SUCCESS) {
53 __environ = environ_ptrs;
54 } else {
55 free(environ_buf);
56 free(environ_ptrs);
57 }
58 return err;
59 }