[Refactor] Implement scriptable Lua API
Large architecture refactor of the scripting system. Previous implementation required Lua scripts to return "action tables" which were interpreted by a large and not very flexible at all if-else ladder in C++. While fine for the initial implementation, it's not scalable, and it makes it impossible for players to write their own meaningful tools.
This commit is contained in:
parent
4b21d30567
commit
e06d6eec37
@ -4,6 +4,7 @@ if not filename then
|
|||||||
return "" -- No arguments, return nothing.
|
return "" -- No arguments, return nothing.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local current_dir = bettola.get_current_dir(context)
|
||||||
local target_node = current_dir.children[filename]
|
local target_node = current_dir.children[filename]
|
||||||
|
|
||||||
if not target_node then
|
if not target_node then
|
||||||
|
|||||||
@ -4,4 +4,4 @@ if not target then
|
|||||||
return "" -- No argument, just return to prompt.
|
return "" -- No argument, just return to prompt.
|
||||||
end
|
end
|
||||||
|
|
||||||
return { action = "cd", target = target }
|
return bettola.cd(context, target)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ if found_redirect then
|
|||||||
return "echo: syntax error: expected filename after '>'"
|
return "echo: syntax error: expected filename after '>'"
|
||||||
end
|
end
|
||||||
local content = table.concat(content_parts, " ")
|
local content = table.concat(content_parts, " ")
|
||||||
return { action = "write_file", target = filename, content = content }
|
return bettola.write_file(context, filename, content)
|
||||||
else
|
else
|
||||||
return table.concat(arg, " ")
|
return table.concat(arg, " ")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
-- /bin/exit - Disconnects from a remote session or cloes terminal window.
|
-- /bin/exit - Disconnects from a remote session or cloes terminal window.
|
||||||
if is_remote_session then
|
if is_remote_session then
|
||||||
return { action = "disconnect" }
|
return bettola.disconnect(context)
|
||||||
else
|
else
|
||||||
return { action = "close_terminal" }
|
return bettola.close_terminal(context)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
-- /bin/ls - Lists files in a directory.
|
-- /bin/ls - Lists files in a directory.
|
||||||
local dir = current_dir -- Get directory object from C++.
|
local dir = bettola.get_current_dir(context)
|
||||||
local output = ""
|
local output = ""
|
||||||
|
|
||||||
-- Iterate over the 'children' map exposed via C++.
|
-- Iterate over the 'children' map exposed via C++.
|
||||||
|
|||||||
@ -6,4 +6,4 @@ if not target_ip then
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Add args such as -sV for version detection etc.
|
-- TODO: Add args such as -sV for version detection etc.
|
||||||
return { action = "scan", target = target_ip }
|
return bettola.nmap(context, target_ip)
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
local file_to_remove = arg[1]
|
local file_to_remove = arg[1]
|
||||||
if not file_to_remove then return "rm: missing operand" end
|
if not file_to_remove then return "rm: missing operand" end
|
||||||
return { action = "rm", target = file_to_remove }
|
return bettola.rm(context, file_to_remove)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
-- /bin/ssh - Connects to a remote host.
|
-- /bin/ssh - Connects to a remote host.
|
||||||
local target = arg[1]
|
local target = arg[1]
|
||||||
if not target then return "ssh: missing operand" end
|
if not target then return "ssh: missing operand" end
|
||||||
return { action = "ssh", target = target }
|
return bettola.ssh(context, target)
|
||||||
|
|||||||
@ -24,6 +24,25 @@ vfs_node* CommandProcessor::get_current_dir(void) {
|
|||||||
return _current_dir;
|
return _current_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Machine* CommandProcessor::get_home_machine(void) { return _home_machine; }
|
||||||
|
Machine* CommandProcessor::get_session_machine(void) { return _session_machine; }
|
||||||
|
|
||||||
|
std::map<std::string, Machine*>&
|
||||||
|
CommandProcessor::get_world_machines(void) {
|
||||||
|
return _world_machines;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
std::string CommandProcessor::process_command(const std::string& command) {
|
||||||
/* Trim trailing whitespace. */
|
/* Trim trailing whitespace. */
|
||||||
std::string cmd = command;
|
std::string cmd = command;
|
||||||
@ -48,13 +67,9 @@ std::string CommandProcessor::process_command(const std::string& command) {
|
|||||||
if(root->children.count("bin") && root->children["bin"]->children.count(script_filename)) {
|
if(root->children.count("bin") && root->children["bin"]->children.count(script_filename)) {
|
||||||
vfs_node* script_node = root->children["bin"]->children[script_filename];
|
vfs_node* script_node = root->children["bin"]->children[script_filename];
|
||||||
bool is_remote = (_session_machine != _home_machine);
|
bool is_remote = (_session_machine != _home_machine);
|
||||||
sol::object result = _lua->execute(script_node->content, _current_dir, args, is_remote);
|
sol::object result = _lua->execute(script_node->content, *this, args, is_remote);
|
||||||
if(result.is<std::string>()) {
|
return result.is<std::string>() ? result.as<std::string>() : "[Script returned an unexpected type]";
|
||||||
return result.as<std::string>();
|
|
||||||
} else if(result.is<sol::table>()) {
|
|
||||||
return _handle_vfs_action(result.as<sol::table>());
|
|
||||||
}
|
|
||||||
return "[Script returned an unexpected type]";
|
|
||||||
}
|
}
|
||||||
return "Unknown command: " + command_name + "\n";
|
return "Unknown command: " + command_name + "\n";
|
||||||
}
|
}
|
||||||
@ -83,145 +98,54 @@ vfs_node* find_node_by_path(vfs_node* root, const std::string& path) {
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CommandProcessor::_handle_vfs_action(sol::table action) {
|
void CommandProcessor::ensure_vfs_is_writable(void) {
|
||||||
std::string action_name = action["action"].get_or<std::string>("");
|
if(!_session_machine->is_vfs_a_copy) {
|
||||||
/* Make the CoW check universal for any write operation. */
|
/* VFS shared, copy required. */
|
||||||
if(action_name == "rm" || action_name == "write_file") {
|
if(_session_machine == _home_machine) {
|
||||||
if(!_session_machine->is_vfs_a_copy) {
|
/* We are modifying our own home machine. */
|
||||||
/* VFS is shared, a copy is required. */
|
fprintf(stderr, "CoW: Write attempt on player's home machine."
|
||||||
if(_session_machine == _home_machine) {
|
"Creating persistent copy.\n");
|
||||||
/* We are modifying our own home machine. */
|
std::string original_path = get_full_path(_current_dir);
|
||||||
fprintf(stderr, "CoW: Write attempt on player's home machine"
|
|
||||||
"Creating persistant copy.\n");
|
vfs_node* new_vfs_root = copy_vfs_node(_home_machine->vfs_root, nullptr);
|
||||||
|
auto* new_machine = new Machine(_home_machine->id, _home_machine->hostname);
|
||||||
|
new_machine->vfs_root = new_vfs_root;
|
||||||
|
new_machine->services = _home_machine->services;
|
||||||
|
new_machine->is_vfs_a_copy = true;
|
||||||
|
|
||||||
|
_home_machine = new_machine;
|
||||||
|
set_session_machine(new_machine);
|
||||||
|
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
||||||
|
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
||||||
|
} else {
|
||||||
|
/* we are modifying a remote NPC machine. */
|
||||||
|
std::string remote_ip = "";
|
||||||
|
for(auto const& [ip, machine] : _world_machines) {
|
||||||
|
if(machine == _session_machine) {
|
||||||
|
remote_ip = ip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!remote_ip.empty()) {
|
||||||
|
fprintf(stderr, "CoW: Write attempt on remote machine '%s'."
|
||||||
|
"Creating persistent copy.\n",
|
||||||
|
remote_ip.c_str());
|
||||||
|
|
||||||
std::string original_path = get_full_path(_current_dir);
|
std::string original_path = get_full_path(_current_dir);
|
||||||
|
|
||||||
vfs_node* new_vfs_root = copy_vfs_node(_home_machine->vfs_root, nullptr);
|
vfs_node* new_vfs_root = copy_vfs_node(_session_machine->vfs_root, nullptr);
|
||||||
auto* new_machine = new Machine(_home_machine->id, _home_machine->hostname);
|
auto* new_machine = new Machine(_session_machine->id, _session_machine->hostname);
|
||||||
new_machine->vfs_root = new_vfs_root;
|
new_machine->vfs_root = new_vfs_root;
|
||||||
new_machine->services = _home_machine->services;
|
new_machine->services = _session_machine->services;
|
||||||
new_machine->is_vfs_a_copy = true; /* Mark as copy. */
|
new_machine->is_vfs_a_copy = true;
|
||||||
|
|
||||||
|
_world_machines[remote_ip] = new_machine;
|
||||||
|
set_session_machine(new_machine);
|
||||||
|
|
||||||
_home_machine = new_machine;
|
|
||||||
_session_machine = new_machine;
|
|
||||||
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
||||||
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
||||||
} else {
|
|
||||||
std::string remote_ip = "";
|
|
||||||
/* Check if we are on a known remote system. */
|
|
||||||
for(auto const& [ip, machine] : _world_machines) {
|
|
||||||
if(machine == _session_machine) {
|
|
||||||
remote_ip = ip;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!remote_ip.empty()) {
|
|
||||||
fprintf(stderr, "CoW: Write attempt on remote machine '%s'. "
|
|
||||||
"Creating persistant copy.\n",
|
|
||||||
remote_ip.c_str());
|
|
||||||
std::string original_path = get_full_path(_current_dir);
|
|
||||||
|
|
||||||
vfs_node* new_vfs_root = copy_vfs_node(_session_machine->vfs_root, nullptr);
|
|
||||||
auto* new_machine = new Machine(_session_machine->id, _session_machine->hostname);
|
|
||||||
new_machine->vfs_root = new_vfs_root;
|
|
||||||
new_machine->services = _session_machine->services;
|
|
||||||
new_machine->is_vfs_a_copy = true; /* Mark as copy. */
|
|
||||||
|
|
||||||
_world_machines[remote_ip] = new_machine;
|
|
||||||
_session_machine = new_machine;
|
|
||||||
|
|
||||||
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
|
||||||
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
|
||||||
} else {
|
|
||||||
return "Permission denied: Filesystem is read-only and not part of the world.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(action_name == "rm") {
|
|
||||||
std::string path = action["target"].get_or<std::string>("");
|
|
||||||
if(path.empty()) return "rm: missing operand";
|
|
||||||
|
|
||||||
if(!_current_dir->children.count(path)) {
|
|
||||||
return std::string("rm: cannot remove '") + path + "': No such file or directory.";
|
|
||||||
}
|
|
||||||
vfs_node* target_node = _current_dir->children[path];
|
|
||||||
if(target_node->type == DIR_NODE) {
|
|
||||||
return std::string("rm: cannot remove '") + path + "': Is a directory.";
|
|
||||||
}
|
|
||||||
_current_dir->children.erase(path);
|
|
||||||
delete target_node;
|
|
||||||
return ""; /* Success. */
|
|
||||||
} else if(action_name == "write_file") {
|
|
||||||
std::string filename = action["target"].get_or<std::string>("");
|
|
||||||
std::string content = action["content"].get_or<std::string>("");
|
|
||||||
if(filename.empty()) {
|
|
||||||
return "write_file: missing filename";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_current_dir->children.count(filename)) {
|
|
||||||
vfs_node* target_node = _current_dir->children[filename];
|
|
||||||
if(target_node->type == DIR_NODE) {
|
|
||||||
return std::string("cannot write to '") + filename + "': Is a directory.";
|
|
||||||
}
|
|
||||||
target_node->content = content;
|
|
||||||
} else {
|
|
||||||
vfs_node* new_file = new vfs_node {
|
|
||||||
.name = filename, .type = FILE_NODE, .content = content,
|
|
||||||
.parent = _current_dir
|
|
||||||
};
|
|
||||||
_current_dir->children[filename] = new_file;
|
|
||||||
}
|
|
||||||
return ""; /* Success. */
|
|
||||||
} else if(action_name == "ssh") {
|
|
||||||
std::string target_ip = action["target"].get_or<std::string>("");
|
|
||||||
if(_world_machines.count(target_ip)) {
|
|
||||||
_session_machine = _world_machines[target_ip];
|
|
||||||
_current_dir = _session_machine->vfs_root;
|
|
||||||
return "Connected to " + target_ip;
|
|
||||||
}
|
|
||||||
return "ssh: Could not resolve hostname " + target_ip + ": Name or service not known";
|
|
||||||
} else if(action_name == "cd") {
|
|
||||||
std::string target_dir_name = action["target"].get_or<std::string>("");
|
|
||||||
if(target_dir_name == "..") {
|
|
||||||
if(_current_dir->parent) {
|
|
||||||
_current_dir = _current_dir->parent;
|
|
||||||
}
|
|
||||||
} else if(_current_dir->children.count(target_dir_name)) {
|
|
||||||
vfs_node* target_node = _current_dir->children[target_dir_name];
|
|
||||||
if(target_node->type == DIR_NODE) {
|
|
||||||
_current_dir = target_node;
|
|
||||||
} else {
|
|
||||||
return std::string("cd: not a directory: ") + target_dir_name;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return std::string("cd: no such file or directory: ") + target_dir_name;
|
|
||||||
}
|
|
||||||
return ""; /* Success. */
|
|
||||||
} else if(action_name == "disconnect") {
|
|
||||||
_session_machine = _home_machine;
|
|
||||||
_current_dir = _home_machine->vfs_root;
|
|
||||||
return "Connection closed.";
|
|
||||||
} else if(action_name == "close_terminal") {
|
|
||||||
return "__CLOSE_CONNECTION__";
|
|
||||||
} else if(action_name == "scan") {
|
|
||||||
std::string target_ip = action["target"].get_or<std::string>("");
|
|
||||||
if(!_world_machines.count(target_ip)) {
|
|
||||||
return std::string("nmap: Could not resolve host: ") + target_ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
Machine* target_machine = _world_machines[target_ip];
|
|
||||||
if(target_machine->services.empty()) {
|
|
||||||
return std::string("No open ports for ") + target_ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss<<"Host: "<<target_ip<<"\n";
|
|
||||||
ss<<"PORT\tSTATE\tSERVICE\n";
|
|
||||||
for(auto const& [port, service_name] : target_machine->services) {
|
|
||||||
ss<<port<<"/tcp\t"<<"open\t"<<service_name<<"\n";
|
|
||||||
}
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
return "Error: Unknown VFS action '" + action_name + "'";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,10 +13,19 @@ public:
|
|||||||
~CommandProcessor(void);
|
~CommandProcessor(void);
|
||||||
|
|
||||||
std::string process_command(const std::string& command);
|
std::string process_command(const std::string& command);
|
||||||
|
|
||||||
|
/* Public interface for API functions. */
|
||||||
vfs_node* get_current_dir(void);
|
vfs_node* get_current_dir(void);
|
||||||
|
Machine* get_home_machine(void);
|
||||||
|
Machine* get_session_machine(void);
|
||||||
|
std::map<std::string, Machine*>& get_world_machines(void);
|
||||||
|
|
||||||
|
void set_current_dir(vfs_node* node);
|
||||||
|
void set_session_machine(Machine* machine);
|
||||||
|
|
||||||
|
void ensure_vfs_is_writable(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _handle_vfs_action(sol::table action);
|
|
||||||
Machine* _home_machine;
|
Machine* _home_machine;
|
||||||
Machine* _session_machine;
|
Machine* _session_machine;
|
||||||
vfs_node* _current_dir;
|
vfs_node* _current_dir;
|
||||||
|
|||||||
102
common/src/lua_api.cpp
Normal file
102
common/src/lua_api.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "lua_api.h"
|
||||||
|
#include "command_processor.h"
|
||||||
|
#include "machine.h"
|
||||||
|
#include "vfs.h"
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
vfs_node* get_current_dir(CommandProcessor& context) {
|
||||||
|
return context.get_current_dir();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rm(CommandProcessor& context, const std::string& filename) {
|
||||||
|
context.ensure_vfs_is_writable();
|
||||||
|
vfs_node* current_dir = context.get_current_dir();
|
||||||
|
if(!current_dir->children.count(filename)) {
|
||||||
|
return "rm: cannot remove '" + filename + "': No such file or directory.";
|
||||||
|
}
|
||||||
|
vfs_node* target_node = current_dir->children[filename];
|
||||||
|
if(target_node->type == DIR_NODE) {
|
||||||
|
return "rm: cannot remove '" + filename + "': Is a directory.";
|
||||||
|
}
|
||||||
|
current_dir->children.erase(filename);
|
||||||
|
delete target_node;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string write_file(CommandProcessor& context, const std::string& filename,
|
||||||
|
const std::string& content) {
|
||||||
|
context.ensure_vfs_is_writable();
|
||||||
|
vfs_node* current_dir = context.get_current_dir();
|
||||||
|
if(current_dir->children.count(filename)) {
|
||||||
|
vfs_node* target_node = current_dir->children[filename];
|
||||||
|
if(target_node->type == DIR_NODE) {
|
||||||
|
return "cannot write to '" + filename + "': Is a directory.";
|
||||||
|
}
|
||||||
|
target_node->content = content;
|
||||||
|
} else {
|
||||||
|
vfs_node* new_file = new vfs_node {
|
||||||
|
.name = filename, .type = FILE_NODE, .content = content, .parent = current_dir};
|
||||||
|
current_dir->children[filename] = new_file;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cd(CommandProcessor& context, const std::string& path) {
|
||||||
|
vfs_node* current_dir = context.get_current_dir();
|
||||||
|
if(path == "..") {
|
||||||
|
if(current_dir->parent) {
|
||||||
|
context.set_current_dir(current_dir->parent);
|
||||||
|
}
|
||||||
|
} else if(current_dir->children.count(path)) {
|
||||||
|
vfs_node* target_node = current_dir->children[path];
|
||||||
|
if(target_node->type == DIR_NODE) {
|
||||||
|
context.set_current_dir(target_node);
|
||||||
|
} else {
|
||||||
|
return "cd: not a directory: " + path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "cd: no such file or directory: " + path;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ssh(CommandProcessor& context, const std::string& ip) {
|
||||||
|
if(context.get_world_machines().count(ip)) {
|
||||||
|
context.set_session_machine(context.get_world_machines().at(ip));
|
||||||
|
return "Connected to " + ip;
|
||||||
|
}
|
||||||
|
return "ssh: Could not resolve hostname " + ip + ": Name or service not found";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string nmap(CommandProcessor& context, const std::string& ip) {
|
||||||
|
if(!context.get_world_machines().count(ip)) {
|
||||||
|
return "nmap: Could not resolve host: " + ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
Machine* target_machine = context.get_world_machines().at(ip);
|
||||||
|
if(target_machine->services.empty()) {
|
||||||
|
return "No open ports for " + ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Host: " << ip << "\n";
|
||||||
|
ss << "PORT\tSTATE\tSERVICE\n";
|
||||||
|
for(auto const& [port, service_name] : target_machine->services) {
|
||||||
|
ss << port << "/tcp\t" << "open\t" << service_name << "\n";
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string disconnect(CommandProcessor& context) {
|
||||||
|
context.set_session_machine(context.get_home_machine());
|
||||||
|
return "Connection closed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string close_terminal(CommandProcessor& context) {
|
||||||
|
return "__CLOSE_CONNECTION__";
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace api */
|
||||||
25
common/src/lua_api.h
Normal file
25
common/src/lua_api.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "vfs.h"
|
||||||
|
|
||||||
|
class CommandProcessor;
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
/* FILESYSTEM ACTIONS. */
|
||||||
|
vfs_node* get_current_dir(CommandProcessor& context);
|
||||||
|
std::string rm(CommandProcessor& context, const std::string& filename);
|
||||||
|
std::string write_file(CommandProcessor& context, const std::string& filename,
|
||||||
|
const std::string& content);
|
||||||
|
std::string cd(CommandProcessor& context, const std::string& path);
|
||||||
|
|
||||||
|
/* NETWORK ACTIONS. */
|
||||||
|
std::string ssh(CommandProcessor& context, const std::string& ip);
|
||||||
|
std::string nmap(CommandProcessor& context, const std::string& ip);
|
||||||
|
std::string disconnect(CommandProcessor& context);
|
||||||
|
|
||||||
|
/* SYSTEM ACTIONS. */
|
||||||
|
std::string close_terminal(CommandProcessor& context);
|
||||||
|
|
||||||
|
} /* namespace api */
|
||||||
@ -1,8 +1,12 @@
|
|||||||
#include "lua_processor.h"
|
|
||||||
#include <sol/forward.hpp>
|
#include <sol/forward.hpp>
|
||||||
#include <sol/object.hpp>
|
#include <sol/object.hpp>
|
||||||
#include <sol/protected_function_result.hpp>
|
#include <sol/protected_function_result.hpp>
|
||||||
|
#include <sol/raii.hpp>
|
||||||
|
|
||||||
|
#include "lua_processor.h"
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
|
#include "lua_api.h"
|
||||||
|
#include "command_processor.h"
|
||||||
|
|
||||||
LuaProcessor::LuaProcessor(void) {
|
LuaProcessor::LuaProcessor(void) {
|
||||||
_lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::io, sol::lib::table);
|
_lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::io, sol::lib::table);
|
||||||
@ -12,16 +16,31 @@ LuaProcessor::LuaProcessor(void) {
|
|||||||
"name", &vfs_node::name,
|
"name", &vfs_node::name,
|
||||||
"type", &vfs_node::type,
|
"type", &vfs_node::type,
|
||||||
"children", &vfs_node::children,
|
"children", &vfs_node::children,
|
||||||
"content", &vfs_node::content); }
|
"content", &vfs_node::content);
|
||||||
|
|
||||||
|
/* Expose CommandProcessor to Lua. DON'T ALLOW SCRIPTS TO CREATE IT THOUGH! */
|
||||||
|
_lua.new_usertype<CommandProcessor>("CommandProcessor", sol::no_constructor);
|
||||||
|
|
||||||
|
/* Create the 'bettola' API table. */
|
||||||
|
sol::table bettola_api = _lua.create_named_table("bettola");
|
||||||
|
bettola_api["rm"] = &api::rm;
|
||||||
|
bettola_api["write_file"] = &api::write_file;
|
||||||
|
bettola_api["get_current_dir"]= &api::get_current_dir;
|
||||||
|
bettola_api["cd"] = &api::cd;
|
||||||
|
bettola_api["ssh"] = &api::ssh;
|
||||||
|
bettola_api["nmap"] = &api::nmap;
|
||||||
|
bettola_api["disconnect"] = &api::disconnect;
|
||||||
|
bettola_api["close_terminal"] = &api::close_terminal;
|
||||||
|
}
|
||||||
|
|
||||||
LuaProcessor::~LuaProcessor(void) {}
|
LuaProcessor::~LuaProcessor(void) {}
|
||||||
|
|
||||||
sol::object LuaProcessor::execute(const std::string& script, vfs_node* current_dir,
|
sol::object LuaProcessor::execute(const std::string& script, CommandProcessor& context,
|
||||||
const std::vector<std::string>& args, bool is_remote) {
|
const std::vector<std::string>& args, bool is_remote) {
|
||||||
try {
|
try {
|
||||||
/* Pass C++ objects/points into the Lua env. */
|
/* Pass C++ objects/points into the Lua env. */
|
||||||
_lua["is_remote_session"] = is_remote;
|
_lua["is_remote_session"] = is_remote;
|
||||||
_lua["current_dir"] = current_dir;
|
_lua["context"] = &context;
|
||||||
|
|
||||||
/* Create and populate the 'arg' table for the script. */
|
/* Create and populate the 'arg' table for the script. */
|
||||||
sol::table arg_table = _lua.create_table();
|
sol::table arg_table = _lua.create_table();
|
||||||
|
|||||||
@ -5,13 +5,15 @@
|
|||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class CommandProcessor;
|
||||||
|
|
||||||
class LuaProcessor {
|
class LuaProcessor {
|
||||||
public:
|
public:
|
||||||
LuaProcessor(void);
|
LuaProcessor(void);
|
||||||
~LuaProcessor(void);
|
~LuaProcessor(void);
|
||||||
|
|
||||||
/* Executes a string of lua code and returns result as a string. */
|
/* Executes a string of lua code and returns result as a string. */
|
||||||
sol::object execute(const std::string& script, vfs_node* current_dir,
|
sol::object execute(const std::string& script, CommandProcessor& context,
|
||||||
const std::vector<std::string>& args, bool is_remote);
|
const std::vector<std::string>& args, bool is_remote);
|
||||||
private:
|
private:
|
||||||
sol::state _lua;
|
sol::state _lua;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user