From 79e4546664b3c44a3f42ab6f34b33c0c485b27c8 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 15 Jan 2025 13:46:21 +1100 Subject: [PATCH] Add source code --- src/main.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/main.cpp diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..df45e8a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,131 @@ +#include +#include +#include + +#include +#include +#include +#include + +using namespace std; + +vector builtInFunctions = {"exit", "cd"}; + +void log(string input) { + cout << input << endl; +} + +string prompt() { + string input; + cout << filesystem::current_path() << " > "; + getline(cin, input); + return input; +} + +string findExecutable(string executable) { + for (int i = 0; i < builtInFunctions.size(); i++) { + if (builtInFunctions[i] == executable) { + return executable; + } + } + if (filesystem::exists(executable)) { + if (executable[0] != '/') { + return "./" + executable; + } + return executable; + } + string output; + vector path = {"/bin", "/usr/bin", "/usr/local/bin"}; + for (int i = 0; i < path.size(); i++) { + output = path[i] + "/" + executable; + if (filesystem::exists(output)) { + return output; + } else { + output.clear(); + } + } + return output; +} + +vector tokenise(string input) { + vector output; + string currentArg; + for (int i = 0; i < input.size(); i++) { + if (input[i] == ' ' && !currentArg.empty()) { + output.push_back(currentArg); + currentArg.clear(); + } else { + currentArg += input[i]; + } + } + if (!currentArg.empty()) { + output.push_back(currentArg); + } + + string executableLocation = findExecutable(output[0]); + if (!executableLocation.empty()) { + output[0] = executableLocation; + } else { + log("Couldn't find an executable in the path"); + output.clear(); + } + + return output; +} + +int runProcess(vector args) { + pid_t pid = fork(); + if (pid == -1) { + cerr << "Fork failed!" << endl; + return -1; + } + if (pid == 0) { + vector cargs; + cargs.push_back(const_cast(args[0].c_str())); + for (int i = 1; i < args.size(); i++) { + cargs.push_back(const_cast(args[i].c_str())); + } + cargs.push_back(nullptr); + execvp(args[0].c_str(), cargs.data()); + + cerr << "Execution failed with error " << strerror(errno) << endl; + _exit(1); + } + int status; + waitpid(pid, &status, 0); + + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } + return -1; +} + +int main(int argc, char *argv[]) { + bool continueLoop = true; + while (continueLoop) { + string input = prompt(); + if (input == "") { + break; + } + vector tokens = tokenise(input); + auto path = filesystem::current_path(); + if (tokens[0] == "exit") { + exit(0); + } else if (tokens[0] == "cd") { + if (tokens.size() == 1) { + log("cd requires an argument"); + } else { + filesystem::current_path(tokens[1]); + } + continue; + } + if (tokens.empty()) { + continue; + } + int returnCode = runProcess(tokens); + if (returnCode != 0) { + log("Process failed with error code " + to_string(returnCode)); + } + } + return 0; +}