]> git.proxmox.com Git - wasi-libc.git/blame - libc-bottom-half/sources/__wasilibc_initialize_environ.c
Add a function to de-initialize the environment-variable state.
[wasi-libc.git] / libc-bottom-half / sources / __wasilibc_initialize_environ.c
CommitLineData
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>
9efc2f42 6#include <wasi/libc-environ.h>
bdfbb545 7
9efc2f42
DG
8/// If the program doesn't use `environ`, it'll get this version of
9/// `__wasilibc_environ`, which isn't initialized with a constructor function.
10/// `getenv` etc. call `__wasilibc_ensure_environ()` before accessing it.
11/// Statically-initialize it to an invalid pointer value so that we can
12/// detect if it's been explicitly initialized (we can't use `NULL` because
13/// `clearenv` sets it to NULL.
14char **__wasilibc_environ __attribute__((weak)) = (char **)-1;
bdfbb545 15
9efc2f42
DG
16// See the comments in libc-environ.h.
17void __wasilibc_ensure_environ(void) {
18 if (__wasilibc_environ == (char **)-1) {
19 __wasilibc_initialize_environ();
20 }
21}
22
23/// Avoid dynamic allocation for the case where there are no environment
24/// variables, but we still need a non-NULL pointer to an (empty) array.
25static char *empty_environ[1] = { NULL };
bdfbb545 26
9efc2f42
DG
27// See the comments in libc-environ.h.
28void __wasilibc_initialize_environ(void) {
bdfbb545
DG
29 // Get the sizes of the arrays we'll have to create to copy in the environment.
30 size_t environ_count;
31 size_t environ_buf_size;
9efc2f42 32 __wasi_errno_t err = __wasi_environ_sizes_get(&environ_count, &environ_buf_size);
446cb3f1 33 if (err != __WASI_ERRNO_SUCCESS) {
410c6607 34 goto oserr;
bdfbb545
DG
35 }
36 if (environ_count == 0) {
9efc2f42 37 __wasilibc_environ = empty_environ;
410c6607 38 return;
bdfbb545
DG
39 }
40
41 // Add 1 for the NULL pointer to mark the end, and check for overflow.
42 size_t num_ptrs = environ_count + 1;
43 if (num_ptrs == 0) {
410c6607 44 goto software;
bdfbb545
DG
45 }
46
47 // Allocate memory for storing the environment chars.
48 char *environ_buf = malloc(environ_buf_size);
49 if (environ_buf == NULL) {
410c6607 50 goto software;
bdfbb545
DG
51 }
52
53 // Allocate memory for the array of pointers. This uses `calloc` both to
54 // handle overflow and to initialize the NULL pointer at the end.
55 char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
56 if (environ_ptrs == NULL) {
57 free(environ_buf);
410c6607 58 goto software;
bdfbb545
DG
59 }
60
9efc2f42
DG
61 // Fill the environment chars, and the `__wasilibc_environ` array with
62 // pointers into those chars.
446cb3f1
DG
63 // TODO: Remove the casts on `environ_ptrs` and `environ_buf` once the witx is updated with char8 support.
64 err = __wasi_environ_get((uint8_t **)environ_ptrs, (uint8_t *)environ_buf);
410c6607 65 if (err != __WASI_ERRNO_SUCCESS) {
bdfbb545
DG
66 free(environ_buf);
67 free(environ_ptrs);
410c6607 68 goto oserr;
bdfbb545 69 }
410c6607 70
9efc2f42 71 __wasilibc_environ = environ_ptrs;
1fad3389 72 return;
410c6607
DG
73oserr:
74 _Exit(EX_OSERR);
75software:
76 _Exit(EX_SOFTWARE);
bdfbb545 77}
82fc2c4f
DG
78
79// See the comments in libc-environ.h.
80void __wasilibc_deinitialize_environ(void) {
81 if (__wasilibc_environ != (char **)-1) {
82 // Let libc-top-half clear the old environment-variable strings.
83 clearenv();
84 // Set the pointer to the special init value.
85 __wasilibc_environ = (char **)-1;
86 }
87}
88
89// See the comments in libc-environ.h.
90__attribute__((weak))
91void __wasilibc_maybe_reinitialize_environ_eagerly(void) {
92 // This version does nothing. It may be overridden by a version which does
93 // something if `environ` is used.
94}