summaryrefslogtreecommitdiff
path: root/src/user/lib/stdlib.c
diff options
context:
space:
mode:
authordzwdz2022-07-11 21:54:51 +0200
committerdzwdz2022-07-11 21:54:51 +0200
commit2e79a2e5af3affa7a6a3becdffb1c91d89af90af (patch)
treec253761c4ec010ad14b08f9ee8dfc1a50411b30f /src/user/lib/stdlib.c
parent6c01d9a7e34e1fccc2775b0e2187ac5e50dd4392 (diff)
user: reorganize the userland sources
Diffstat (limited to 'src/user/lib/stdlib.c')
-rw-r--r--src/user/lib/stdlib.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/user/lib/stdlib.c b/src/user/lib/stdlib.c
new file mode 100644
index 0000000..c055d04
--- /dev/null
+++ b/src/user/lib/stdlib.c
@@ -0,0 +1,120 @@
+#include <user/lib/stdlib.h>
+#include <shared/printf.h>
+#include <shared/syscalls.h>
+
+// TODO oh god this garbage - malloc, actually open, [...]
+static libc_file _stdin_null = { .fd = 0 };
+static libc_file _stdout_null = { .fd = 1 };
+
+libc_file *stdin = &_stdin_null, *stdout = &_stdout_null;
+
+static void backend_file(void *arg, const char *buf, size_t len) {
+ file_write((libc_file*)arg, buf, len);
+}
+
+int printf(const char *fmt, ...) {
+ int ret = 0;
+ va_list argp;
+ va_start(argp, fmt);
+ ret = __printf_internal(fmt, argp, backend_file, (void*)stdout);
+ va_end(argp);
+ return ret;
+}
+
+static void backend_buf(void *arg, const char *buf, size_t len) {
+ char **ptrs = arg;
+ size_t space = ptrs[1] - ptrs[0];
+ if (len > space) len = space;
+ memcpy(ptrs[0], buf, len);
+ ptrs[0] += len;
+}
+
+int snprintf(char *str, size_t len, const char *fmt, ...) {
+ int ret = 0;
+ char *ptrs[2] = {str, str + len};
+ va_list argp;
+ va_start(argp, fmt);
+ ret = __printf_internal(fmt, argp, backend_buf, &ptrs);
+ va_end(argp);
+ if (ptrs[0] < ptrs[1]) *ptrs[0] = '\0';
+ return ret;
+}
+
+int _klogf(const char *fmt, ...) {
+ // idiotic. however, this hack won't matter anyways
+ char buf[256];
+ int ret = 0;
+ char *ptrs[2] = {buf, buf + sizeof buf};
+ va_list argp;
+ va_start(argp, fmt);
+ ret = __printf_internal(fmt, argp, backend_buf, &ptrs);
+ va_end(argp);
+ if (ptrs[0] < ptrs[1]) *ptrs[0] = '\0';
+ _syscall_debug_klog(buf, ret);
+ return ret;
+}
+
+
+libc_file *file_open(const char *path, int flags) {
+ handle_t h = _syscall_open(path, strlen(path), flags);
+ libc_file *f;
+ if (h < 0) return NULL;
+
+ f = malloc(sizeof *f);
+ if (!f) {
+ _syscall_close(h);
+ return NULL;
+ }
+ f->pos = 0;
+ f->eof = false;
+ f->fd = h;
+ return f;
+}
+
+libc_file *file_reopen(libc_file *f, const char *path, int flags) {
+ /* partially based on the musl implementation of freopen */
+ libc_file *f2;
+ if (!path) goto fail;
+ f2 = file_open(path, flags);
+ if (!f2) goto fail;
+
+ /* shouldn't happen, but if it happens, let's roll with it. */
+ if (f->fd == f2->fd) f2->fd = -1;
+
+ if (_syscall_dup(f2->fd, f->fd, 0) < 0) goto fail2;
+ f->pos = f2->pos;
+ f->eof = f2->eof;
+ file_close(f2);
+ return f;
+
+fail2:
+ file_close(f2);
+fail:
+ file_close(f);
+ return NULL;
+}
+
+int file_read(libc_file *f, char *buf, size_t len) {
+ if (f->fd < 0) return -1;
+
+ int res = _syscall_read(f->fd, buf, len, f->pos);
+ if (res < 0) return res;
+ if (res == 0 && len > 0) f->eof = true;
+ f->pos += res;
+ return res;
+}
+
+int file_write(libc_file *f, const char *buf, size_t len) {
+ if (f->fd < 0) return -1;
+
+ int res = _syscall_write(f->fd, buf, len, f->pos);
+ if (res < 0) return res;
+ f->pos += res;
+ return res;
+}
+
+void file_close(libc_file *f) {
+ if (f->fd > 0) _syscall_close(f->fd);
+ if (f != &_stdin_null && f != &_stdout_null)
+ free(f);
+}