summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib/exit.c
diff options
context:
space:
mode:
authorKacper <kacper@mail.openlinux.dev>2025-12-07 20:10:31 +0100
committerKacper <kacper@mail.openlinux.dev>2025-12-07 20:10:31 +0100
commitfc00c656c96528112d05cf0edf8631bd5eaea446 (patch)
treea6e0e6c588191a8bd1c64afc3b7a258e3e66c236 /lib/libc/stdlib/exit.c
Add build system scaffolding and libc headers
Diffstat (limited to 'lib/libc/stdlib/exit.c')
-rw-r--r--lib/libc/stdlib/exit.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/libc/stdlib/exit.c b/lib/libc/stdlib/exit.c
new file mode 100644
index 00000000..34b8a0f2
--- /dev/null
+++ b/lib/libc/stdlib/exit.c
@@ -0,0 +1,69 @@
+#include <io.h>
+#include <libc.h>
+#include <unistd.h>
+#include <stdio.h>
+
+void (*__dummy_atexit_fvec)(void);
+weak_reference(__dummy_atexit_fvec, __atexit_fvec);
+
+void (*__dummy_stdio_cleanup)(void);
+weak_reference(__dummy_stdio_cleanup, __stdio_cleanup);
+
+static void __fclose(FILE *fp)
+{
+ if (fp == NULL) {
+ return;
+ }
+
+ if (fp->buf_len > 0) {
+ fflush(fp);
+ }
+
+ if (fp->fd > STDERR_FILENO) {
+ close(fp->fd);
+ }
+
+ if (fp->buf) {
+ free(fp->buf);
+ }
+
+ if (fp != stdout && fp != stderr && fp != stdin) {
+ free(fp);
+ }
+}
+
+static void __stdio_cleanup_impl(void)
+{
+ write(1, "HELLO\n", 6);
+ fflush(stdout);
+
+ if (stdout->next != NULL) {
+ FILE *cur = stdout->next;
+ while (cur) {
+ struct __FILE *next = cur->next;
+ __fclose(cur);
+ cur = next;
+ }
+ }
+}
+
+void exit(int status)
+{
+ void (*fptr)(void);
+
+ /* Only do stdio cleanup if it was referenced (meaning stdio was used)
+ */
+ if (__stdio_cleanup) {
+ __stdio_cleanup_impl();
+ }
+
+ if (__atexit_fvec) {
+ fptr = __atexit_fvec;
+ while (fptr) {
+ fptr();
+ fptr++;
+ }
+ }
+
+ _exit(status);
+}