diff --git a/apps/cat.cpp b/apps/cat.cpp index e4799b5c..8523b8df 100644 --- a/apps/cat.cpp +++ b/apps/cat.cpp @@ -1,34 +1,27 @@ +#include #include +#include -#include -#include -#include +using os::File; -static void do_cat(StringView path) +static Result do_cat(StringView path) { - FILE* f; + SharedPtr f; - if (path == "-") f = stdin; + auto out = File::standard_output(); + + if (path == "-") f = File::standard_input(); else - { - f = fopen(path.chars(), "r"); - if (!f) - { - perror(path.chars()); - exit(1); - } - } - - char buffer[4096]; + f = TRY(File::open(path, File::ReadOnly)); while (1) { - size_t nread = fread(buffer, 1, sizeof(buffer), f); - if (nread == 0) return; - fwrite(buffer, 1, nread, stdout); + String line = TRY(f->read_line()); + if (line.is_empty()) break; + out->write(line.view()); } - if (f != stdin) fclose(f); + return {}; } Result luna_main(int argc, char** argv) @@ -37,11 +30,11 @@ Result luna_main(int argc, char** argv) os::ArgumentParser parser; parser.add_positional_argument(filename, "file"_sv, "-"_sv); - Vector extra_files = parser.parse(argc, argv).value(); + Vector extra_files = TRY(parser.parse(argc, argv)); - do_cat(filename); + TRY(do_cat(filename)); - for (auto file : extra_files) { do_cat(file); } + for (auto file : extra_files) TRY(do_cat(file)); return 0; } diff --git a/apps/edit.cpp b/apps/edit.cpp index 5c7ff17a..1bfe0c9e 100644 --- a/apps/edit.cpp +++ b/apps/edit.cpp @@ -1,9 +1,8 @@ +#include #include #include -#include -#include -#include +using os::File; Result luna_main(int argc, char** argv) { @@ -13,15 +12,15 @@ Result luna_main(int argc, char** argv) parser.add_positional_argument(pathname, "path"_sv, true); parser.parse(argc, argv); - auto file = TRY(os::File::open_or_create(pathname, os::File::WriteOnly)); + auto file = TRY(File::open_or_create(pathname, File::WriteOnly)); - char buffer[4096]; + auto input = File::standard_input(); while (1) { - char* rc = fgets(buffer, sizeof(buffer), stdin); - if (rc == 0) break; - TRY(file->write(StringView { buffer })); + String line = TRY(input->read_line()); + if (line.is_empty()) break; + TRY(file->write(line.view())); } return 0; diff --git a/libluna/src/CppABI.cpp b/libluna/src/CppABI.cpp index 1026204c..53fdc4bd 100644 --- a/libluna/src/CppABI.cpp +++ b/libluna/src/CppABI.cpp @@ -1,6 +1,54 @@ +typedef void* (*cxa_atexit_func_t)(void*); + +struct cxa_atexit_entry +{ + cxa_atexit_func_t function; + void* argument; + void* dso_handle; +}; + +#define CXA_ATEXIT_MAX 64 + +int cxa_atexit_entry_count = 0; + +cxa_atexit_entry cxa_atexit_entries[CXA_ATEXIT_MAX]; + extern "C" { void __gxx_personality_v0() { } + + int __cxa_atexit(cxa_atexit_func_t func, void* arg, void* dso) + { + if (cxa_atexit_entry_count >= CXA_ATEXIT_MAX) return -1; + cxa_atexit_entries[cxa_atexit_entry_count].function = func; + cxa_atexit_entries[cxa_atexit_entry_count].argument = arg; + cxa_atexit_entries[cxa_atexit_entry_count].dso_handle = dso; + cxa_atexit_entry_count++; + return 0; + } + + void __cxa_finalize(void* f) + { + int i = cxa_atexit_entry_count; + if (!f) + { + while (i--) + { + if (cxa_atexit_entries[i].function) { cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); } + } + } + else + { + while (i--) + { + if (cxa_atexit_entries[i].function == (cxa_atexit_func_t)f) + { + cxa_atexit_entries[i].function(cxa_atexit_entries[i].argument); + cxa_atexit_entries[i].function = 0; + } + } + } + } } diff --git a/libluna/src/StringBuilder.cpp b/libluna/src/StringBuilder.cpp index 22e9097f..8ee9065c 100644 --- a/libluna/src/StringBuilder.cpp +++ b/libluna/src/StringBuilder.cpp @@ -29,7 +29,7 @@ Result StringBuilder::add(unsigned long value) Result StringBuilder::add(char value) { - return format("%c"_sv, value); + return m_data.append_data((const u8*)&value, 1); } Result StringBuilder::format(StringView fmt, ...) diff --git a/libos/include/os/File.h b/libos/include/os/File.h index f5cd2fdc..0fe8a863 100644 --- a/libos/include/os/File.h +++ b/libos/include/os/File.h @@ -24,15 +24,24 @@ namespace os static Result> open_or_create(StringView path, OpenMode flags, mode_t mode = 0644); static Result> create(StringView path, OpenMode flags, mode_t mode = 0644); + static SharedPtr standard_input(); + static SharedPtr standard_output(); + static SharedPtr standard_error(); + void set_close_on_exec(); Result write(StringView str); + Result read_line(); + + Result getchar(); + File(Badge); ~File(); private: static Result> construct(StringView path, int flags, mode_t mode); + static void initialize_standard_streams(); Result raw_read(u8* buf, usize length); Result raw_write(const u8* buf, usize length); diff --git a/libos/src/File.cpp b/libos/src/File.cpp index 3ae3dbf6..6fa92fe6 100644 --- a/libos/src/File.cpp +++ b/libos/src/File.cpp @@ -1,8 +1,13 @@ #include +#include #include #include #include +static SharedPtr g_stdin = {}; +static SharedPtr g_stdout = {}; +static SharedPtr g_stderr = {}; + namespace os { File::File(Badge) @@ -14,9 +19,45 @@ namespace os if (m_fd >= 0) close(m_fd); } + void File::initialize_standard_streams() + { + g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({})) + .expect_release_value("Cannot open standard input stream"); + g_stdin->m_fd = STDIN_FILENO; + + g_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({})) + .expect_release_value("Cannot open standard output stream"); + g_stdout->m_fd = STDOUT_FILENO; + + g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({})) + .expect_release_value("Cannot open standard error stream"); + g_stderr->m_fd = STDERR_FILENO; + } + + SharedPtr File::standard_input() + { + if (!g_stdin) initialize_standard_streams(); + + return g_stdin; + } + + SharedPtr File::standard_output() + { + if (!g_stdout) initialize_standard_streams(); + + return g_stdout; + } + + SharedPtr File::standard_error() + { + if (!g_stderr) initialize_standard_streams(); + + return g_stderr; + } + Result> File::construct(StringView path, int flags, mode_t mode) { - auto file = TRY(adopt_shared(new (std::nothrow) File({}))); + auto file = TRY(adopt_shared_if_nonnull(new (std::nothrow) File({}))); long rc = syscall(SYS_open, path.chars(), flags, mode); int fd = TRY(Result::from_syscall(rc)); @@ -60,6 +101,39 @@ namespace os return {}; } + Result File::read_line() + { + Vector data; + + int current; + while (true) + { + current = TRY(getchar()); + + if (current == -1) break; + + TRY(data.try_append((char)current)); + + if (current == '\n') break; + } + + if (!data.size()) return String {}; + + TRY(data.try_append('\0')); + + return String::from_cstring(data.data()); + } + + Result File::getchar() + { + char value; + + usize nread = TRY(raw_read((u8*)&value, 1)); + if (!nread) return -1; + + return value; + } + void File::set_close_on_exec() { fcntl(m_fd, F_SETFD, FD_CLOEXEC);