#include #include #include "command_processor.h" #include "db/database_manager.h" #include "vfs.h" #include "lua_api.h" #include "lua_processor.h" #include "machine_manager.h" #include "machine.h" vfs_node* find_node_by_id(vfs_node* root, long long id) { if(root->id == id) { return root; } for(auto const& [name, child] : root->children) { vfs_node* found = find_node_by_id(child, id); if(found) { return found; } } return nullptr; } CommandProcessor::CommandProcessor(Machine* home_machine, std::map& world_machines, DatabaseManager* db_manager, MachineManager* machine_manager) : _machine_manager(machine_manager), _db_manager(db_manager), _home_machine(home_machine), _session_machine(home_machine), _world_machines(world_machines) { _lua = new LuaProcessor(); _current_dir = _session_machine->vfs_root; } CommandProcessor::~CommandProcessor(void) { delete _lua; } vfs_node* CommandProcessor::get_current_dir(void) { return _current_dir; } Machine* CommandProcessor::get_home_machine(void) { return _home_machine; } Machine* CommandProcessor::get_session_machine(void) { return _session_machine; } std::map& CommandProcessor::get_world_machines(void) { return _world_machines; } DatabaseManager* CommandProcessor::get_db_manager(void) { return _db_manager; } MachineManager* CommandProcessor::get_machine_manager(void) { return _machine_manager; } void CommandProcessor::set_current_dir(vfs_node* node) { _current_dir = node; } void CommandProcessor::set_session_machine(Machine* machine) { _session_machine = machine; if(_session_machine) { _current_dir = _session_machine->vfs_root; } } std::string CommandProcessor::process_command(const std::string& command) { /* Trim trailing whitespace. */ std::string cmd = command; size_t end = cmd.find_last_not_of(" \t\n\r"); cmd = (end == std::string::npos) ? "" : cmd.substr(0, end+1); /* === Generic script executer. === */ /* Parse the command and it's arguments. */ std::stringstream ss(cmd); std::string command_name; ss >> command_name; std::vector args; std::string arg; while(ss >> arg) { args.push_back(arg); } /* Search for script in the /bin directory of the current session machine. */ std::string script_filename = command_name + ".lua"; long long script_id = 0; std::string script_content; _db_manager->_db << "SELECT T2.id, T2.content FROM vfs_nodes AS T1 JOIN vfs_nodes AS T2 " "ON T1.id = T2.parent_id WHERE T1.name = 'bin' AND T2.name = ? " "AND t1.machine_id = ?;" << script_filename << _session_machine->id >> [&](long long id, std::string content) { script_id = id; script_content = content; }; if(script_id > 0) { bool is_remote = (_session_machine != _home_machine); sol::object result = _lua->execute(script_content, *this, args, is_remote); return result.is() ? result.as() : "[Script returned an unexpected type]"; } return "Unknown command: " + command_name + "\n"; } std::string CommandProcessor::write_file(const std::string& path, const std::string& content) { return api::write_file(*this, path, content); } /* Find a VFS node by it's absolute path. */ vfs_node* find_node_by_path(vfs_node* root, const std::string& path) { if(path == "/") { return root; } vfs_node* current = root; std::stringstream ss(path); std::string segment; /* Discard the first empty segment that comes form the leading '/'. */ if(path[0] == '/') { std::getline(ss, segment, '/'); } while(std::getline(ss, segment, '/')) { if(current->type == DIR_NODE && current->children.count(segment)) { current = current->children[segment]; } else { return nullptr; /* Path segmenet not found. */ } } return current; } std::string CommandProcessor::read_file(const std::string& path) { vfs_node* root = get_session_machine()->vfs_root; vfs_node* node = find_node_by_path(root, path); if(node && node->type == FILE_NODE) { return node->content; } return "Error: file not found."; }