From e6915fb6dd715e39e37702a6d69c220c0f1798bf Mon Sep 17 00:00:00 2001
From: Benji Dial <benji@benjidial.net>
Date: Wed, 31 Jul 2024 17:16:21 -0400
Subject: [PATCH] remove argc, argv; arguments will be passed via environment
 variables

---
 applications/clock/source/main.cpp            |  2 +-
 applications/goldman/source/main.cpp          |  2 +-
 applications/hello/source/main.cpp            |  2 +-
 applications/init/source/main.cpp             |  5 +--
 documentation/kernel-interfaces/app-entry.txt |  3 --
 documentation/kernel-interfaces/syscalls.txt  |  5 ++-
 euler/source/entry.cpp                        | 19 ++--------
 kernel/include/hilbert/kernel/application.hpp | 10 ++++-
 kernel/include/hilbert/kernel/utility.hpp     |  7 +++-
 kernel/source/application.cpp                 | 37 ++++++++++++++++++-
 kernel/source/entry.cpp                       |  4 --
 kernel/source/syscall.cpp                     |  5 ++-
 12 files changed, 64 insertions(+), 37 deletions(-)
 delete mode 100644 documentation/kernel-interfaces/app-entry.txt

diff --git a/applications/clock/source/main.cpp b/applications/clock/source/main.cpp
index 3a1270d..fde8f33 100644
--- a/applications/clock/source/main.cpp
+++ b/applications/clock/source/main.cpp
@@ -38,7 +38,7 @@ std::string the_time() {
 
 }
 
-int main(int, char **) {
+int main() {
 
   font = new daguerre::fixed_font<bool>(
     daguerre::try_load_psf("/assets/terminus/10x18-bold.psf").value());
diff --git a/applications/goldman/source/main.cpp b/applications/goldman/source/main.cpp
index 475129f..2ade412 100644
--- a/applications/goldman/source/main.cpp
+++ b/applications/goldman/source/main.cpp
@@ -9,7 +9,7 @@
 
 renderer *r;
 
-int main(int, char **) {
+int main() {
 
   euler::syscall::listener_handle listener;
   euler::syscall::create_socket_listener("hilbert.compositor", listener);
diff --git a/applications/hello/source/main.cpp b/applications/hello/source/main.cpp
index b297721..64f569e 100644
--- a/applications/hello/source/main.cpp
+++ b/applications/hello/source/main.cpp
@@ -4,7 +4,7 @@
 
 daguerre::fixed_font<bool> *font;
 
-int main(int, char **) {
+int main() {
 
   font = new daguerre::fixed_font<bool>(
     daguerre::try_load_psf("/assets/terminus/10x18-bold.psf").value());
diff --git a/applications/init/source/main.cpp b/applications/init/source/main.cpp
index c281bc0..66ad260 100644
--- a/applications/init/source/main.cpp
+++ b/applications/init/source/main.cpp
@@ -1,9 +1,6 @@
 #include <euler/syscall.hpp>
 
-//this does not keep track of the processes or whether they have started
-//successfully, nor does it set their argc, argv, stdin, stdout, or stderr.
-
-int main(int, char **) {
+int main() {
   euler::syscall::process_handle dummy;
   euler::syscall::start_process("/bin/compositor", {}, {}, dummy);
   euler::syscall::start_process("/bin/clock", {}, {}, dummy);
diff --git a/documentation/kernel-interfaces/app-entry.txt b/documentation/kernel-interfaces/app-entry.txt
deleted file mode 100644
index 1a09d22..0000000
--- a/documentation/kernel-interfaces/app-entry.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-on entry, the stack is set up, and all registers other than rsp are set to 0.
-the ARGC environment variable holds the number of arguments to main.
-the ARGV0, ARGV1, ARGV2, etc environment variables hold those arguments.
diff --git a/documentation/kernel-interfaces/syscalls.txt b/documentation/kernel-interfaces/syscalls.txt
index f7dddba..de00451 100644
--- a/documentation/kernel-interfaces/syscalls.txt
+++ b/documentation/kernel-interfaces/syscalls.txt
@@ -157,7 +157,10 @@ start process:
     qword: stream handle here
     qword: new stream handle in child
       new handle must be < 65536
-  any gifted streams must not have threads waiting to read from our end
+  any gifted streams must not have threads waiting to read from our end.
+  any environment variables in the current process whose names do not begin
+  with an underscore are also set in the child process. the environment
+  variables in the process start info override any with the same name.
 
 end this process:
   rax in: 17
diff --git a/euler/source/entry.cpp b/euler/source/entry.cpp
index ab721f1..b888027 100644
--- a/euler/source/entry.cpp
+++ b/euler/source/entry.cpp
@@ -2,28 +2,15 @@
 #include <cstdlib>
 #include <string>
 
-int main(int argc, char **argv);
+int main();
 
 extern "C" [[noreturn]] void _start() {
 
   //TODO: call static initializers
 
-  auto argc_raw = euler::syscall::try_get_environment_variable("ARGC");
-  int argc = argc_raw.has_value() ? std::stoi(argc_raw.value()) : 0;
+  int exit_code = main();
 
-  std::vector<std::string> argv;
-
-  for (int i = 0; i < argc; ++i) {
-    std::string arg_name = std::string("ARGV") + std::to_string(i);
-    auto arg_raw = euler::syscall::try_get_environment_variable(arg_name);
-    argv.push_back(arg_raw.has_value() ? arg_raw.value() : "");
-  }
-
-  std::vector<char *> c_argv(argc);
-  for (int i = 0; i < argc; ++i)
-    c_argv[i] = argv[i].data();
-
-  int exit_code = main(argc, c_argv.data());
+  //TODO: call at_exit stuff
 
   euler::syscall::end_this_process(exit_code);
 
diff --git a/kernel/include/hilbert/kernel/application.hpp b/kernel/include/hilbert/kernel/application.hpp
index e7c7d2e..9c2e851 100644
--- a/kernel/include/hilbert/kernel/application.hpp
+++ b/kernel/include/hilbert/kernel/application.hpp
@@ -104,6 +104,7 @@ namespace hilbert::kernel::application {
     utility::id_allocator<generic_stream_ptr> open_streams;
     utility::id_allocator<socket_listener *> running_socket_listeners;
 
+  public:
     struct string_pair {
       utility::string a;
       utility::string b;
@@ -111,6 +112,9 @@ namespace hilbert::kernel::application {
 
     utility::list<string_pair> environment_variables;
 
+  private:
+    string_pair *find_environment_variable(const utility::string &name);
+
   public:
     utility::string name;
 
@@ -126,10 +130,12 @@ namespace hilbert::kernel::application {
     process(app_memory *memory, const utility::string &name);
     ~process();
 
-    //arguments are utility::move'd
-    void add_environment_variable(
+    void set_environment_variable(
       utility::string &&name, utility::string &&value);
 
+    void set_environment_variable(
+      const utility::string &name, const utility::string &value);
+
     //null if unset
     utility::string *get_environment_variable(const utility::string &name);
 
diff --git a/kernel/include/hilbert/kernel/utility.hpp b/kernel/include/hilbert/kernel/utility.hpp
index b0ced32..3fe14b0 100644
--- a/kernel/include/hilbert/kernel/utility.hpp
+++ b/kernel/include/hilbert/kernel/utility.hpp
@@ -212,7 +212,12 @@ namespace hilbert::kernel::utility {
         buffer[i] = other.buffer[i];
     }
 
-    vector(vector &&other) = delete;
+    vector(vector &&other)
+      : buffer(other.buffer),
+        buffer_len(other.buffer_len),
+        count(other.count) {
+      other.buffer = 0;
+    }
 
     ~vector() {
       if (buffer)
diff --git a/kernel/source/application.cpp b/kernel/source/application.cpp
index 6df49cd..cd76bd9 100644
--- a/kernel/source/application.cpp
+++ b/kernel/source/application.cpp
@@ -90,9 +90,42 @@ namespace hilbert::kernel::application {
     delete memory; //:p
   }
 
-  void process::add_environment_variable(
+  process::string_pair *process::find_environment_variable(
+    const utility::string &name) {
+
+    for (auto *n = environment_variables.first; n; n = n->next)
+      if (n->value.a == name)
+        return &n->value;
+
+    return 0;
+
+  }
+
+  void process::set_environment_variable(
     utility::string &&name, utility::string &&value) {
-    environment_variables.insert_end({.a = name, .b = value});
+
+    auto *sp = find_environment_variable(name);
+    if (sp)
+      sp->b = utility::move(value);
+    else
+      environment_variables.insert_end({
+        .a = utility::move(name),
+        .b = utility::move(value)
+      });
+
+  }
+
+  void process::set_environment_variable(
+    const utility::string &name, const utility::string &value) {
+
+    auto *sp = find_environment_variable(name);
+    if (sp)
+      sp->b = value;
+    else
+      environment_variables.insert_end({
+        .a = name, .b = value
+      });
+
   }
 
   utility::string *process::get_environment_variable(
diff --git a/kernel/source/entry.cpp b/kernel/source/entry.cpp
index 73e79c7..f412838 100644
--- a/kernel/source/entry.cpp
+++ b/kernel/source/entry.cpp
@@ -218,10 +218,6 @@ extern "C" [[noreturn]] void entry() {
 
   application::process *init_process =
     new application::process(init_memory, utility::string("init", 4));
-  init_process->add_environment_variable(
-    utility::string("ARGC", 4), utility::string("1", 1));
-  init_process->add_environment_variable(
-    utility::string("ARGV0", 5), utility::string("/bin/init", 9));
   application::add_process(init_process);
 
   application::thread *init_thread =
diff --git a/kernel/source/syscall.cpp b/kernel/source/syscall.cpp
index 803f7d2..00590c9 100644
--- a/kernel/source/syscall.cpp
+++ b/kernel/source/syscall.cpp
@@ -625,8 +625,11 @@ namespace hilbert::kernel::syscall {
     application::process *p =
       new application::process(memory, file.dir_entry.name);
 
+    for (auto *n = owner->environment_variables.first; n; n = n->next)
+      p->set_environment_variable(n->value.a, n->value.b);
+
     for (uint64_t i = 0; i < psi->env_var_count; ++i)
-      p->add_environment_variable(
+      p->set_environment_variable(
         utility::string(psi->env_vars[i].name, psi->env_vars[i].name_len),
         utility::string(psi->env_vars[i].value, psi->env_vars[i].value_len));