summaryrefslogtreecommitdiffstats
path: root/libc-bottom-half/sources/__main_void.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc-bottom-half/sources/__main_void.c')
-rw-r--r--libc-bottom-half/sources/__main_void.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/libc-bottom-half/sources/__main_void.c b/libc-bottom-half/sources/__main_void.c
new file mode 100644
index 0000000..cba22ef
--- /dev/null
+++ b/libc-bottom-half/sources/__main_void.c
@@ -0,0 +1,54 @@
+#include <wasi/api.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+// The user's `main` function, expecting arguments.
+int __main_argc_argv(int argc, char *argv[]);
+
+// If the user's `main` function expects arguments, the compiler will rename
+// it to `__main_argc_argv`, and this version will get linked in, which
+// initializes the argument data and calls `__main_argc_argv`.
+__attribute__((__weak__, nodebug))
+int __main_void(void) {
+ __wasi_errno_t err;
+
+ // Get the sizes of the arrays we'll have to create to copy in the args.
+ size_t argv_buf_size;
+ size_t argc;
+ err = __wasi_args_sizes_get(&argc, &argv_buf_size);
+ if (err != __WASI_ERRNO_SUCCESS) {
+ _Exit(EX_OSERR);
+ }
+
+ // Add 1 for the NULL pointer to mark the end, and check for overflow.
+ size_t num_ptrs = argc + 1;
+ if (num_ptrs == 0) {
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Allocate memory for storing the argument chars.
+ char *argv_buf = malloc(argv_buf_size);
+ if (argv_buf == NULL) {
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Allocate memory for the array of pointers. This uses `calloc` both to
+ // handle overflow and to initialize the NULL pointer at the end.
+ char **argv = calloc(num_ptrs, sizeof(char *));
+ if (argv == NULL) {
+ free(argv_buf);
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Fill the argument chars, and the argv array with pointers into those chars.
+ // TODO: Remove the casts on `argv_ptrs` and `argv_buf` once the witx is updated with char8 support.
+ err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf);
+ if (err != __WASI_ERRNO_SUCCESS) {
+ free(argv_buf);
+ free(argv);
+ _Exit(EX_OSERR);
+ }
+
+ // Call `__main_argc_argv` with the arguments!
+ return __main_argc_argv(argc, argv);
+}