Skip to content

Commit

Permalink
refactor: unfriend Shell and Command class
Browse files Browse the repository at this point in the history
Co-authored-by: Lumynous <[email protected]>
  • Loading branch information
Young-TW and lumynou5 committed Jun 25, 2024
1 parent d641a8b commit 088ba2f
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 87 deletions.
6 changes: 3 additions & 3 deletions include/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ class Command {
int assign(std::vector<std::string>& args);
int assign(Command& cmd);

std::string get();

int parse();
int exec();

bool empty();

std::vector<std::string> arg(); // return arg
const std::vector<std::string>& arg() const; // return arg

private:
std::string command;
std::vector<std::string> args;
int runtime_status = 0;

friend class Shell;
};

#endif
8 changes: 5 additions & 3 deletions include/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ class Shell {
VariableManager vars;
VariableManager functions;

int exec_cmd(const Command& cmd);

private:
std::ifstream fin;
std::ofstream fout;
int output();
std::string read();
std::string read(std::istream& input_stream);
int exec_shell_builtin(const std::vector<std::string>& arg);
int exec_shell_builtin(const Command& cmd);
std::vector<Command> read_script(const std::filesystem::path& file);
int read_history();
int write_history(const std::string& cmd);
Expand All @@ -41,6 +43,8 @@ class Shell {
std::filesystem::path history_file;
std::filesystem::path config_dir;

int exec_file(const Command& cmd);

int cmd_alias(const std::vector<std::string>& arg);
int cmd_cd(const std::vector<std::string>& arg);
int cmd_echo(const std::vector<std::string>& arg);
Expand All @@ -49,8 +53,6 @@ class Shell {
int cmd_ls(const std::vector<std::string>& arg);
int cmd_pwd(const std::vector<std::string>& arg);
int cmd_set(const std::vector<std::string>& arg);

friend class Command;
};

static Shell shell;
Expand Down
74 changes: 3 additions & 71 deletions src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ int Command::assign(Command& cmd) {
return 0;
}

std::string Command::get() { return this->command; }

int Command::parse() {
if (shell.functions.exist(this->command)) {
Command alias_cmd = shell.functions.get(this->command);
Expand Down Expand Up @@ -120,76 +122,6 @@ int Command::parse() {
return 0;
}

int Command::exec() {
if (this->args.empty()) {
return 0;
}

if (shell.functions.exist(this->args[0])) {
for (const auto& cmd :
string_parser(shell.functions.get(args[0]), '\n')) {
Command command(cmd);
this->runtime_status = command.exec();
}

return this->runtime_status;
}

int shell_builtin_ans = shell.exec_shell_builtin(this->args);

if (shell_builtin_ans != 127) {
return shell_builtin_ans;
}

std::unique_ptr<char*[]> argv = std::make_unique<char*[]>(args.size() + 1);
for (size_t i = 0; i < this->args.size(); i++) {
argv[i] = this->args[i].data();
}

std::string cmd_path_str;

if (std::filesystem::exists(args[0]) &&
std::filesystem::is_regular_file(args[0])) {
cmd_path_str = this->args[0];
} else {
std::vector<std::string> cmd_paths =
string_parser(shell.vars.get("PATH"), ':');

for (const auto& cmd : cmd_paths) {
std::filesystem::path cmd_path =
cmd / std::filesystem::path(args[0]);

if (std::filesystem::exists(cmd_path) &&
std::filesystem::is_regular_file(cmd_path)) {
cmd_path_str = cmd_path.lexically_normal().string();
break;
}
}
}

if (cmd_path_str.empty()) {
fmt::print(stderr, "Error: command `{}` not found.\n", args[0]);
return 127;
}

pid_t pid = fork();

if (pid == -1) {
return -1;
}

if (pid > 0) {
int status;
waitpid(pid, &status, 0);
return status;
}

signal(SIGINT, SIG_DFL);

execve(cmd_path_str.c_str(), argv.get(), environ);
unreachable();
}

bool Command::empty() { return this->command.empty(); }

std::vector<std::string> Command::arg() { return this->args; }
const std::vector<std::string>& Command::arg() const { return this->args; }
2 changes: 1 addition & 1 deletion src/commands/alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ int Shell::cmd_alias(const std::vector<std::string>& arg) {

Command alias_cmd = Command(arg[2]);

this->functions.set(arg[1], alias_cmd.command);
this->functions.set(arg[1], alias_cmd.get());
return 0;
}
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) {
Command command;
command.assign(result["command"].as<std::string>());
command.parse();
return command.exec();
return shell.exec_cmd(command);
}

if (result.unmatched().size() > 0) {
Expand Down
81 changes: 73 additions & 8 deletions src/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ int Shell::run(cxxopts::ParseResult& result) {
break;
}

runtime_status = command.exec();
runtime_status = exec_cmd(command);
if (!command.empty()) {
this->write_history(command.command);
this->write_history(command.get());
}
} while (!std::cin.eof());

Expand All @@ -123,10 +123,10 @@ int Shell::write_history(const std::string& cmd) {
int Shell::run(const std::filesystem::path& file) {
std::vector<Command> commands = read_script(file);
for (auto& command : commands) {
if (!command.command.empty()) {
if (!command.empty()) {
command.parse();
shell.runtime_status = command.exec();
this->write_history(command.command);
shell.runtime_status = exec_cmd(command);
this->write_history(command.get());
}
}

Expand Down Expand Up @@ -279,7 +279,7 @@ std::string Shell::read(std::istream& input_stream) {
return input;
}

int Shell::exec_shell_builtin(const std::vector<std::string>& arg) {
int Shell::exec_shell_builtin(const Command& cmd) {
using CommandType = int (Shell::*)(const std::vector<std::string>&);

static const std::unordered_map<std::string, CommandType> command_map{
Expand All @@ -289,10 +289,75 @@ int Shell::exec_shell_builtin(const std::vector<std::string>& arg) {
{"pwd", &Shell::cmd_pwd}, {"set", &Shell::cmd_set},
};

auto command_it = command_map.find(arg[0]);
auto command_it = command_map.find(cmd.arg()[0]);
if (command_it != command_map.cend()) {
return (this->*(command_it->second))(arg);
return (this->*(command_it->second))(cmd.arg());
}

return 127;
}

int Shell::exec_cmd(const Command& cmd) {
if (functions.exist(cmd.arg()[0])) {
for (const auto& cmd_str : string_parser(functions.get(cmd.arg()[0]), '\n')) {
Command command(cmd_str);
runtime_status = exec_cmd(command);
}

return runtime_status;
}

exec_file(cmd);

return exec_shell_builtin(cmd);
}

int Shell::exec_file(const Command& cmd) {
std::unique_ptr<char*[]> argv = std::make_unique<char*[]>(cmd.arg().size() + 1);
for (size_t i = 0; i < cmd.arg().size(); i++) {
argv[i] = const_cast<char*>(cmd.arg()[i].c_str());
}

std::string file_path_str;

if (std::filesystem::exists(cmd.arg()[0]) &&
std::filesystem::is_regular_file(cmd.arg()[0])) {
file_path_str = cmd.arg()[0];
} else {
std::vector<std::string> file_pathes =
string_parser(shell.vars.get("PATH"), ':');

for (const auto& file : file_pathes) {
std::filesystem::path file_path =
file / std::filesystem::path(cmd.arg()[0]);

if (std::filesystem::exists(file_path) &&
std::filesystem::is_regular_file(file_path)) {
file_path_str = file_path.lexically_normal().string();
break;
}
}
}

if (file_path_str.empty()) {
fmt::print(stderr, "Error: command `{}` not found.\n", cmd.arg()[0]);
return 127;
}

pid_t pid = fork();

if (pid == -1) {
return -1;
}

if (pid > 0) {
int status;
waitpid(pid, &status, 0);
return status;
}

signal(SIGINT, SIG_DFL);

execve(file_path_str.c_str(), argv.get(), environ);
unreachable();
}

0 comments on commit 088ba2f

Please sign in to comment.