#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(BinaryFormat::create_loader(interpreter, m_recursion_level + 1)); u64 entry = TRY(loader->load(space)); m_interpreter_cmdline = TRY(loader->cmdline(interpreter_path, move(m_interpreter_cmdline))); return entry; } Result> ScriptLoader::cmdline(const String& path, Vector args) { Vector new_args; TRY(new_args.try_reserve(m_interpreter_cmdline.size() + args.size() + 1)); for (auto& arg : m_interpreter_cmdline) { TRY(new_args.try_append(move(arg))); } auto arg = TRY(path.clone()); TRY(new_args.try_append(move(arg))); for (usize i = 1; i < args.size(); i++) { TRY(new_args.try_append(move(args[i]))); } return new_args; } ScriptLoader::ScriptLoader(SharedPtr inode, int recursion_level) : BinaryFormatLoader(inode, recursion_level) { } Result> ScriptLoader::create(SharedPtr inode, void*, int recursion_level) { return (SharedPtr)TRY(make_shared(inode, recursion_level)); }