diff --git a/src/main.cpp b/src/main.cpp index f411ac0..da332a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,12 +10,13 @@ #include #include #include +#include using namespace std; -vector builtInFunctions = {"exit", "cd", "sub"}; +vector functions = {"exit", "cd", "sub", "listsubs", "set", "get", "run"}; -vector>> substitutions = {{"ls", {"ls", "--color"}}}; +vector>> substitutions; void log(string input) { cout << input << endl; @@ -43,9 +44,30 @@ string prompt() { return input; } +vector getPath() { + string pathstr = getenv("PATH"); + if (pathstr == "") { + log("WARNING! SPACE CANNOT FIND THE PATH! Please ensure your path is set as an environment variable in your Spacefile, or one of Space's parents has set the PATH environment variable. For now, enjoy the default path :)"); + } else { + vector path; + string buffer; + for (int i = 0; i < pathstr.size(); i++) { + if (pathstr[i] == ':') { + path.push_back(buffer); + buffer = ""; + } else { + buffer += pathstr[i]; + } + } + path.push_back(buffer); + return path; + } + return {"/bin", "/usr/bin", "/usr/local/bin"}; +} + string findExecutable(string executable) { - for (int i = 0; i < builtInFunctions.size(); i++) { - if (builtInFunctions[i] == executable) { + for (int i = 0; i < functions.size(); i++) { + if (functions[i] == executable) { return executable; } } @@ -56,7 +78,7 @@ string findExecutable(string executable) { return executable; } string output; - vector path = {"/bin", "/usr/bin", "/usr/local/bin"}; + vector path = getPath(); for (int i = 0; i < path.size(); i++) { output = path[i] + "/" + executable; if (filesystem::exists(output)) { @@ -139,30 +161,91 @@ vector tokeniseSubstitutions(string input) { } 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())); + if (args[0] == "exit") { + exit(0); + } else if (args[0] == "cd") { + if (args.size() == 1) { + log("cd requires an argument"); + return 1; + } else { + filesystem::current_path(args[1]); } - 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); + } else if (args[0] == "set") { + if (args.size() < 3) { + log("set requires 2 arguments"); + return 1; + } + string envStr = (args[1] + "=" + args[2]); + char* cEnvStr = strdup(envStr.c_str()); + putenv(cEnvStr); + } else if (args[0] == "get") { + if (args.size() < 2) { + log("get requires an argument"); + return 1; + } + char* value = getenv(args[1].c_str()); + if (value == nullptr) { + log("Environment variable " + args[1] + " not found"); + return 1; + } + cout << value << endl; + } else if (args[0] == "sub") { + if (args.size() < 3) { + log("substitute requires 2 arguments"); + return 1; + } + vector subArgs = tokeniseSubstitutions(args[2]); + substitutions.push_back({args[1], subArgs}); + } else if (args[0] == "listsubs") { + log("Substitutions:"); + for (int i = 0; i < substitutions.size(); i++) { + string substring; + for (int j = 0; j < substitutions[i].second.size(); j++) { + substring += substitutions[i].second[j] + " "; + } + cout << substitutions[i].first << " -> " << substring << endl; + } + } else { + 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); + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } + return -1; } - return -1; + return 0; +} + +void runScript(string script) { + string scriptLine; + ifstream scriptFile(script); + while (getline(scriptFile, scriptLine)) { + vector tokens = tokenise(scriptLine); + if (tokens.empty()) continue; + int returnCode = runProcess(tokens); + if (returnCode != 0) { + log("Script error:\nCommand " + tokens[0] + " failed with exit code " + to_string(returnCode)); + } + } + scriptFile.close(); } void doStartup() { @@ -186,7 +269,13 @@ void doStartup() { } } +void handler(int signum); + int main(int argc, char *argv[]) { + signal(SIGINT, handler); + if (argc > 1) { + runScript(argv[2]); + } doStartup(); bool continueLoop = true; while (continueLoop) { @@ -196,33 +285,6 @@ int main(int argc, char *argv[]) { } 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; - } else if (tokens[0] == "sub") { - if (tokens.size() < 3) { - log("substitute requires 2 arguments"); - continue; - } - vector args = tokeniseSubstitutions(tokens[2]); - substitutions.push_back({tokens[1], args}); - continue; - } else if (tokens[0] == "listsubs") { - log("Substitutions:"); - for (int i = 0; i < substitutions.size(); i++) { - string substring; - for (int j = 0; j < substitutions[i].second.size(); j++) { - substring += substitutions[i].second[j] + " "; - } - cout << substitutions[i].first << " -> " << substring << endl; - } - } if (tokens.empty()) { continue; } @@ -233,3 +295,7 @@ int main(int argc, char *argv[]) { } return 0; } + +void handler(int signum) { + main(1, nullptr); +}