#include #include #include #include #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 \" -> Installs a wirekit to execute programs with" << std::endl; std::cout << " -> The shared object to be installed as wirekit" << std::endl; std::cout << " -> (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 \" -> Removes a wirekit from the system" << std::endl; std::cout << " -> The name of the wirekit to be uninstalled" << std::endl; std::cout << " \"rewire list\" -> Lists all installed wirekits" << std::endl; std::cout << " \"rewire \"" << std::endl; std::cout << " -> The wirekit to use for execution" << std::endl; std::cout << " -> Can either be installed or in current working directory" << std::endl; std::cout << " -> (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 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 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; }