225 lines
6.4 KiB
C++
225 lines
6.4 KiB
C++
#include <iostream>
|
|
#include <filesystem>
|
|
#include <vector>
|
|
#include <sstream>
|
|
|
|
#include "cli.hpp"
|
|
#include "dl.hpp"
|
|
#include "install.hpp"
|
|
#include "interface.hpp"
|
|
|
|
int launch_help(int argc, char** argv) {
|
|
std::cout << "Use rewire via one of the following commands:" << std::endl;
|
|
|
|
std::cout << " \"rewire help\" -> You appear to already know what it does ;)" << std::endl;
|
|
|
|
std::cout << " \"rewire install <wirekit.so> <name>\" -> Installs a wirekit to execute programs with" << std::endl;
|
|
std::cout << " <wirekit.so> -> The shared object to be installed as wirekit" << std::endl;
|
|
std::cout << " <name> -> (Optional) The name via which the wirekit is supposed to be used" << std::endl;
|
|
std::cout << " -> Defaults to \"wirekit\" when installing \"wirekit.so\"" << std::endl;
|
|
|
|
std::cout << " \"rewire uninstall <name>\" -> Removes a wirekit from the system" << std::endl;
|
|
std::cout << " <name> -> The name of the wirekit to be uninstalled" << std::endl;
|
|
|
|
std::cout << " \"rewire list\" -> Lists all installed wirekits" << std::endl;
|
|
|
|
std::cout << " \"rewire <wirekit> <command+args>\"" << std::endl;
|
|
std::cout << " <wirekit> -> The wirekit to use for execution" << std::endl;
|
|
std::cout << " -> Can either be installed or in current working directory" << std::endl;
|
|
std::cout << " <command+args> -> (Optional) A command to be executed" << std::endl;
|
|
std::cout << " -> Acts as rewired shell if no command is given" << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int launch_install(int argc, char** argv) {
|
|
if (argc < 3 || argc > 4) {
|
|
std::cout << "Invalid usage, try \"rewire help\" for more information!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
InstallManager im;
|
|
if (!im) {
|
|
std::cout << "Unable to manage installations!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
auto kitcheck = [](const std::filesystem::path& kit) -> bool {
|
|
DL tmp_dl { kit };
|
|
if (!tmp_dl) {
|
|
std::cout << "Failed to check wirekit requirements for installation!" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!tmp_dl.resolve("wirekit_prepare")) {
|
|
std::cout << "Wirekit must implement \"wirekit_prepare\" to be installed!" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!tmp_dl.resolve("wirekit_command_start")) {
|
|
std::cout << "Wirekit must implement \"wirekit_command_start\" to be installed!" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
if (!im.install(argv[2], (argc == 4 ? argv[3] : nullptr), kitcheck)) {
|
|
std::cout << "Failed to install wirekit!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "Successfully installed wirekit!" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
int launch_uninstall(int argc, char** argv) {
|
|
if (argc != 3) {
|
|
std::cout << "Invalid usage, try \"rewire help\" for more information!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
InstallManager im;
|
|
if (!im) {
|
|
std::cout << "Unable to manage installations!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (!im.uninstall(argv[2])) {
|
|
std::cout << "Failed to uninstall wirekit!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "Successfully uninstalled wirekit!" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
int launch_list(int argc, char** argv) {
|
|
if (argc != 2) {
|
|
std::cout << "Invalid usage, try \"rewire help\" for more information!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
InstallManager im;
|
|
if (!im) {
|
|
std::cout << "Unable to access installations!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
auto wirekits = im.installs();
|
|
if (wirekits.empty()) {
|
|
std::cout << "Currently, no wirekits are installed!" << std::endl;
|
|
} else {
|
|
std::cout << "Currently, the following wirekits are installed:" << std::endl;
|
|
for (const std::string& kit : wirekits)
|
|
std::cout << " \"" << kit << "\"" << std::endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int launch_run(int argc, char** argv) {
|
|
if (argc < 2) {
|
|
std::cout << "Invalid usage, try \"rewire help\" for more information!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
InstallManager im;
|
|
if (!im) {
|
|
std::cout << "Unable to access installations!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
std::filesystem::path wirekit_path;
|
|
if (!im.get(argv[1], wirekit_path)) {
|
|
std::cout << "No wirekit named \"" << argv[1] << "\" is installed!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
DL wirekit { wirekit_path };
|
|
if (!wirekit) {
|
|
std::cout << "Unable to load wirekit!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// Collect wirekit control function handles
|
|
KitInterface ki;
|
|
ki.prepare = (err_t(*)())wirekit.resolve("wirekit_prepare");
|
|
ki.command_start = (err_t(*)(int, const char* const*))wirekit.resolve("wirekit_command_start");
|
|
ki.command_exit = (void(*)())wirekit.resolve("wirekit_command_exit");
|
|
ki.subject_start = (void(*)())wirekit.resolve("wirekit_subject_start");
|
|
ki.subject_exit = (void(*)())wirekit.resolve("wirekit_subject_exit");
|
|
|
|
// Initialize rewire (internally prepares wirekit)
|
|
if (!rewire_init(ki)) {
|
|
std::cout << "Rewire and wirekit preparation failed!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// Execute commands in rewired syscall environment
|
|
if (argc > 2) {
|
|
rewire_run(argc - 2, (const char**)(argv + 2));
|
|
} else {
|
|
// Shell mode
|
|
while (true) {
|
|
std::cout << "> ";
|
|
|
|
std::string command;
|
|
std::getline(std::cin, command);
|
|
|
|
// Split command at whitespaces
|
|
std::stringstream command_stream { command };
|
|
std::vector<std::string> command_split; // No need to reserve, presumably not many elements
|
|
|
|
std::string part;
|
|
while (command_stream >> std::quoted(part))
|
|
command_split.emplace_back(std::move(part));
|
|
|
|
if (command_split.empty())
|
|
continue;
|
|
|
|
if (command_split[0] == "exit")
|
|
break;
|
|
|
|
// Compile argv (cstr pointer array)
|
|
std::vector<const char*> command_split_cstr;
|
|
command_split_cstr.resize(command_split.size() + 1, nullptr); // +1 for nullptr termination
|
|
|
|
for (std::size_t i = 0; i < command_split.size(); i++)
|
|
command_split_cstr[i] = command_split[i].c_str();
|
|
|
|
// Execute command
|
|
rewire_run((int)command_split_cstr.size() - 1, command_split_cstr.data());
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 2) {
|
|
std::cout << "Invalid usage, try \"rewire help\"!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
LAUNCH_MODE lm = launch_mode(argv[1]);
|
|
|
|
switch (lm) {
|
|
case LAUNCH_MODE::HELP:
|
|
return launch_help(argc, argv);
|
|
case LAUNCH_MODE::INSTALL:
|
|
return launch_install(argc, argv);
|
|
case LAUNCH_MODE::UNINSTALL:
|
|
return launch_uninstall(argc, argv);
|
|
case LAUNCH_MODE::LIST:
|
|
return launch_list(argc, argv);
|
|
case LAUNCH_MODE::RUN:
|
|
return launch_run(argc, argv);
|
|
default:
|
|
std::cout << "Invalid launch mode!" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|