summaryrefslogtreecommitdiff
path: root/src/init/stdlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/init/stdlib.c')
-rw-r--r--src/init/stdlib.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/init/stdlib.c b/src/init/stdlib.c
index a02eb7c..4d26c2e 100644
--- a/src/init/stdlib.c
+++ b/src/init/stdlib.c
@@ -2,7 +2,11 @@
#include <shared/printf.h>
#include <shared/syscalls.h>
-libc_file *stdin, *stdout;
+// 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);
@@ -67,6 +71,29 @@ libc_file *file_open(const char *path, int flags) {
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;
@@ -88,5 +115,6 @@ int file_write(libc_file *f, const char *buf, size_t len) {
void file_close(libc_file *f) {
if (f->fd > 0) _syscall_close(f->fd);
- free(f);
+ if (f != &_stdin_null && f != &_stdout_null)
+ free(f);
}