diff options
Diffstat (limited to 'programs/libc/start.c')
| -rw-r--r-- | programs/libc/start.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/programs/libc/start.c b/programs/libc/start.c new file mode 100644 index 0000000..5e56239 --- /dev/null +++ b/programs/libc/start.c @@ -0,0 +1,72 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> + +void _start(void) +{ + /* clang mangles main if argc/argv are present: + * https://reviews.llvm.org/D127888 */ + int __main_argc_argv(int, char *[]); + int __wnix_argc(void) __attribute__(( + __import_module__("wnix"), + __import_name__("argc") + )); + _Noreturn void __wnix_exit(int) __attribute__(( + __import_module__("wnix"), + __import_name__("exit") + )); + + if (!(__stdin = fopen("/dev/stdin", "rb")) + || !(__stdout = fopen("/dev/stdout", "wb")) + || !(__stderr = fopen("/dev/stderr", "wb"))) + __wnix_exit(EXIT_FAILURE); + + const int argc = __wnix_argc(); + char **argv = malloc((argc + 1) * sizeof *argv); + + if (!argv) + __wnix_exit(EXIT_FAILURE); + + for (int i = 0; i < argc; i++) + { + size_t __wnix_arglen(int) __attribute__(( + __import_module__("wnix"), + __import_name__("arglen") + )); + + int __wnix_argcopy(int, char *, int *) __attribute__(( + __import_module__("wnix"), + __import_name__("argcopy") + )); + + char *const arg = malloc(__wnix_arglen(i)); + + if (!arg) + __wnix_exit(EXIT_FAILURE); + + __wnix_argcopy(i, arg, &errno); + argv[i] = arg; + } + + argv[argc] = NULL; + __wnix_exit(__main_argc_argv(argc, argv)); +} |
