mirror of
https://git.proxmox.com/git/wasi-libc
synced 2025-07-15 17:24:03 +00:00

* Link `populate_args` only if we actually need command-line arguments. This avoids linking in the argv/argc initialization code, and the __wasi_args_sizes_get and __wasi_args_get imports, in programs that don't use command-line arguments. The way this works is, if the user writes `int main(int argc, char *argv[])`, the argument initialization code is loaded, and if they write `int main(void)`, it's not loaded. This promotes the `__original_main` mechanism into an effective contract between the compiler and libc, which wasn't its original purpose, however it seems to fit this purpose quite well. * Document that `__original_main` may be the user's zero-arg `main`.
54 lines
1.6 KiB
C
54 lines
1.6 KiB
C
#include <wasi/core.h>
|
|
#include <wasi/libc.h>
|
|
#include <stdlib.h>
|
|
#include <sysexits.h>
|
|
|
|
// The user's `main` function, expecting arguments.
|
|
int main(int argc, char *argv[]);
|
|
|
|
// If the user's `main` function expects arguments, the compiler won't emit
|
|
// an `__original_main` function so this version will get linked in, which
|
|
// initializes the argument data and calls `main`.
|
|
int __original_main(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_ESUCCESS) {
|
|
_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.
|
|
err = __wasi_args_get(argv, argv_buf);
|
|
if (err != __WASI_ESUCCESS) {
|
|
free(argv_buf);
|
|
free(argv);
|
|
_Exit(EX_OSERR);
|
|
}
|
|
|
|
// Call main with the arguments!
|
|
return main(argc, argv);
|
|
}
|