#include #include #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; } string getHomeDir() { struct passwd* pw = getpwuid(getuid()); if (pw && pw->pw_dir) return string(pw->pw_dir); return ""; } 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 if (input[i] == '~') { currentArg += getHomeDir(); } 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; }