examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 96e8d55747cc8e0e1b0082464be2ca874567976b
parent e40ef4b5852d4a92d198f57dd42f15693ee1190b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Tue, 16 Aug 2022 23:07:18 +0100

hush: Make hush actually work as a shell

Diffstat:
Msrc/hush.cpp | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 68 insertions(+), 7 deletions(-)

diff --git a/src/hush.cpp b/src/hush.cpp @@ -2,10 +2,42 @@ #include <sstream> #include <cstdlib> #include <memory> +#include <vector> +#include <map> #include <unistd.h> +#include <sys/wait.h> +#include <err.h> using namespace std; +void show_clear_warn(char const* msg) +{ + if (errno) + perror(msg); + errno = 0; +} + +int cd(std::vector<char*> const& argv) +{ + if (argv.size() < 2) + { + cerr << "cd: not enough arguments\n"; + return 1; + } + if (argv.size() > 2) + { + cerr << "cd: too many arguments\n"; + return 1; + } + int res = chdir(argv[1]); + show_clear_warn("cd"); + return res; +} + +map<string, int(*)(std::vector<char*> const&)> intrinsics = { + {"cd", cd} +}; + auto pwd(void) -> unique_ptr<char, void(*)(void*)> { @@ -16,21 +48,50 @@ int main(int, char**) { string buf; - auto wd = pwd(); - for (;;) { + auto wd = pwd(); + cout << '[' << wd.get() << "] " << flush; if (!getline(cin, buf)) break; - cout << buf << '\n'; - istringstream is(buf); - while (getline(is, buf, '\0')) - cout << " " << buf; + vector<string> args; + while (getline(is, buf, ' ')) + args.push_back(buf); + + if (args.empty()) + { + cout << '\n'; + continue; + } + string arg0 = args.front(); + std::vector<char*> argp; + for (auto& a : args) + { + a.push_back('\0'); + argp.push_back(a.data()); + } + + if (intrinsics.contains(arg0)) + { + intrinsics[arg0](argp); + continue; + } + argp.push_back(nullptr); - cout << '\n'; + if (fork()) + { + int status; + wait(&status); + if (WEXITSTATUS(status)) + std::cout << "\nResult: " << WEXITSTATUS(status) << '\n'; + } else + { + execvp(argp[0], argp.data()); + err(66, "execv"); + } } cout << "Done!\n";