summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2022-07-11 20:53:03 +0200
committerdzwdz2022-07-11 20:53:03 +0200
commit6c01d9a7e34e1fccc2775b0e2187ac5e50dd4392 (patch)
treef047b55ad061c3a1dcd8d9be89e8aaf47c462979
parent5c4fb3b3c58a2d850031e9449b5d65887e42f1c7 (diff)
init: file_reopen, keep stdin/stdout on their standard fds
-rw-r--r--src/init/main.c22
-rw-r--r--src/init/stdlib.c32
-rw-r--r--src/init/stdlib.h1
3 files changed, 40 insertions, 15 deletions
diff --git a/src/init/main.c b/src/init/main.c
index 1674f8c..88553e9 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -19,7 +19,7 @@ int main(void) {
// allocate bss
_syscall_memflag(&_bss_start, &_bss_end - &_bss_start, MEMFLAG_PRESENT);
- stdout = file_open("/com1", 0);
+ file_reopen(stdout, "/com1", 0);
printf("preinit\n");
/* move everything provided by the kernel to /kdev */
@@ -55,12 +55,14 @@ int main(void) {
}
if (!_syscall_fork(0, NULL)) {
- libc_file *new = file_open("/kdev/com1", 0);
- if (!new) {
+ if (!file_reopen(stdout, "/kdev/com1", 0)) {
+ printf("couldn't open /kdev/com1\n"); // TODO borked
+ _syscall_exit(1);
+ }
+ if (!file_reopen(stdin, "/kdev/com1", 0)) {
printf("couldn't open /kdev/com1\n");
_syscall_exit(1);
}
- stdout = stdin = new; // TODO file_clone, this is bad
shell_loop();
_syscall_exit(1);
@@ -68,17 +70,11 @@ int main(void) {
if (!_syscall_fork(0, NULL)) {
- libc_file *new;
- new = file_open("/vga_tty", 0);
- if (!new) {
- printf("couldn't open /vga_tty\n");
+ if (!file_reopen(stdout, "/vga_tty", 0)) {
+ printf("couldn't open /vga_tty\n"); // TODO borked
_syscall_exit(1);
}
- file_close(stdout);
- stdout = new;
-
- stdin = file_open("/keyboard", 0);
- if (!stdin) {
+ if (!file_reopen(stdin, "/keyboard", 0)) {
printf("couldn't open /keyboard\n");
_syscall_exit(1);
}
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);
}
diff --git a/src/init/stdlib.h b/src/init/stdlib.h
index f7917da..e1e753d 100644
--- a/src/init/stdlib.h
+++ b/src/init/stdlib.h
@@ -15,6 +15,7 @@ typedef struct {
bool eof;
} libc_file;
libc_file *file_open(const char *path, int flags);
+libc_file *file_reopen(libc_file*, const char *path, int flags);
int file_read(libc_file*, char *buf, size_t len);
int file_write(libc_file*, const char *buf, size_t len);
void file_close(libc_file*);