aboutsummaryrefslogtreecommitdiff
path: root/programs/libc/start.c
diff options
context:
space:
mode:
Diffstat (limited to 'programs/libc/start.c')
-rw-r--r--programs/libc/start.c72
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));
+}