diff --git a/base/etc/init/00-home b/base/etc/init/00-home index 1e470d45..1db95930 100644 --- a/base/etc/init/00-home +++ b/base/etc/init/00-home @@ -1,4 +1,4 @@ Name=mount-home Description=Mount the user's home directory on a writable filesystem. -Script=/etc/startup/mount-home.sh +Command=/etc/startup/mount-home.sh Wait=true diff --git a/base/etc/startup/mount-home.sh b/base/etc/startup/mount-home.sh index e78b22ec..612a350d 100644 --- a/base/etc/startup/mount-home.sh +++ b/base/etc/startup/mount-home.sh @@ -1,2 +1,3 @@ +#!/bin/sh mount -t tmpfs tmpfs /home/selene chown selene:selene /home/selene diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 88cbefa7..fe8fe087 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -62,6 +62,7 @@ set(SOURCES src/fs/InitRD.cpp src/binfmt/ELF.cpp src/binfmt/BinaryFormat.cpp + src/binfmt/Script.cpp ) if("${LUNA_ARCH}" MATCHES "x86_64") diff --git a/kernel/src/binfmt/BinaryFormat.cpp b/kernel/src/binfmt/BinaryFormat.cpp index 35ea39c0..4b8be629 100644 --- a/kernel/src/binfmt/BinaryFormat.cpp +++ b/kernel/src/binfmt/BinaryFormat.cpp @@ -1,5 +1,6 @@ #include "binfmt/BinaryFormat.h" #include "binfmt/ELF.h" +#include "binfmt/Script.h" struct BinaryFormatDescriptor { @@ -12,6 +13,7 @@ Vector g_binary_formats; Result BinaryFormat::init() { TRY(register_binary_format(ELFLoader::create, nullptr)); + TRY(register_binary_format(ScriptLoader::create, nullptr)); return {}; } diff --git a/kernel/src/binfmt/BinaryFormat.h b/kernel/src/binfmt/BinaryFormat.h index b8b5e8ec..e37d106f 100644 --- a/kernel/src/binfmt/BinaryFormat.h +++ b/kernel/src/binfmt/BinaryFormat.h @@ -10,7 +10,7 @@ class BinaryFormatLoader : public Shareable virtual StringView format() const = 0; - virtual Result> cmdline(const String& path, Vector args) = 0; + virtual Result> cmdline(Vector args) = 0; virtual ~BinaryFormatLoader() = default; diff --git a/kernel/src/binfmt/ELF.cpp b/kernel/src/binfmt/ELF.cpp index 0d2c39c6..4a5ed642 100644 --- a/kernel/src/binfmt/ELF.cpp +++ b/kernel/src/binfmt/ELF.cpp @@ -132,7 +132,7 @@ Result ELFLoader::load(AddressSpace* space) return elf_header.e_entry; } -Result> ELFLoader::cmdline(const String&, Vector args) +Result> ELFLoader::cmdline(Vector args) { return args; } diff --git a/kernel/src/binfmt/ELF.h b/kernel/src/binfmt/ELF.h index 3db1a59e..7448cec5 100644 --- a/kernel/src/binfmt/ELF.h +++ b/kernel/src/binfmt/ELF.h @@ -55,7 +55,7 @@ class ELFLoader : public BinaryFormatLoader Result sniff() override; Result load(AddressSpace* space) override; - Result> cmdline(const String& path, Vector args) override; + Result> cmdline(Vector args) override; StringView format() const override { diff --git a/kernel/src/binfmt/Script.cpp b/kernel/src/binfmt/Script.cpp new file mode 100644 index 00000000..4c7bc6e0 --- /dev/null +++ b/kernel/src/binfmt/Script.cpp @@ -0,0 +1,61 @@ +#include "binfmt/Script.h" +#include "binfmt/ELF.h" +#include "thread/Scheduler.h" + +#define SHEBANG "#!" + +Result ScriptLoader::sniff() +{ + u8 buf[2]; + usize nread = TRY(m_inode->read(buf, 0, sizeof buf)); + if (nread < 2) return false; + + return !memcmp(buf, SHEBANG, 2); +} + +Result ScriptLoader::load(AddressSpace* space) +{ + u8 buf[256]; + usize nread = TRY(m_inode->read(buf, 2, 255)); + if (!nread) return err(ENOEXEC); + for (usize i = 0; i < nread; i++) + { + if (buf[i] == '\n') buf[i] = '\0'; + else if (buf[i] == '\r' && (i + 1) < nread && buf[i + 1] == '\n') + buf[i] = buf[i + 1] = '\0'; + else + continue; + break; + } + + auto view = StringView { (const char*)buf }; + m_interpreter_cmdline = TRY(view.split(" ")); + if (!m_interpreter_cmdline.size()) return err(ENOEXEC); + + auto& interpreter_path = m_interpreter_cmdline[0]; + auto* current = Scheduler::current(); + + auto interpreter = + TRY(VFS::resolve_path(interpreter_path.chars(), current->auth, current->current_directory, true)); + if (!VFS::can_execute(interpreter, current->auth)) return err(EACCES); + + auto loader = TRY(ELFLoader::create(interpreter, nullptr)); + return loader->load(space); +} + +Result> ScriptLoader::cmdline(Vector args) +{ + Vector new_args; + for (auto& arg : m_interpreter_cmdline) { TRY(new_args.try_append(move(arg))); } + for (auto& arg : args) { TRY(new_args.try_append(move(arg))); } + return new_args; +} + +ScriptLoader::ScriptLoader(SharedPtr inode) : BinaryFormatLoader(inode) +{ +} + +Result> ScriptLoader::create(SharedPtr inode, void*) +{ + return (SharedPtr)TRY(make_shared(inode)); +} diff --git a/kernel/src/binfmt/Script.h b/kernel/src/binfmt/Script.h new file mode 100644 index 00000000..ffbe92bb --- /dev/null +++ b/kernel/src/binfmt/Script.h @@ -0,0 +1,25 @@ +#pragma once +#include "binfmt/BinaryFormat.h" +#include "fs/VFS.h" +#include "memory/AddressSpace.h" + +class ScriptLoader : public BinaryFormatLoader +{ + public: + Result sniff() override; + Result load(AddressSpace* space) override; + + Result> cmdline(Vector args) override; + + StringView format() const override + { + return "script"; + } + + ScriptLoader(SharedPtr inode); + + static Result> create(SharedPtr inode, void*); + + private: + Vector m_interpreter_cmdline; +}; diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 4bfb5ae5..58c979ed 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -80,7 +80,7 @@ Result sys_execve(Registers* regs, SyscallArgs args) auto image = TRY(ThreadImage::try_load_from_binary(loader)); - argv = TRY(loader->cmdline(move(path), move(argv))); + argv = TRY(loader->cmdline(move(argv))); u64 user_argv = TRY(image->push_string_vector_on_stack(argv)); usize user_argc = argv.size();