/** Last Edit: 30/4/2021 **/
#include <iostream>
#include <signal.h>
#include "Commands.h"
int main(int argc, char *argv[]) {
while (true)
{
SmallShell &smash = SmallShell::getInstance();
std::string cmd_line;
std::getline(std::cin, cmd_line);
smash.executeCommand(cmd_line.c_str());
}
return 0;
}
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <vector>
#include <sstream>
#include <sys/wait.h>
#include <iterator>
#include <csignal>
#include <limits.h>
#include <sys/fcntl.h>
#include "Commands.h"
using std::cout;
using std::endl;
using std::cerr;
const int NOT_FOUND = -1;
extern bool keep_running;
string _ltrim(const string &s) {
size_t start = s.find_first_not_of(WHITESPACE);
return (start == string::npos) ? "" : s.substr(start);
}
string _rtrim(const string &s) {
size_t end = s.find_last_not_of(WHITESPACE);
return (end == string::npos) ? "" : s.substr(0, end + 1);
}
string _trim(const string &s) {
return _rtrim(_ltrim(s));
}
int _parseCommandLine(const string &cmd_line, vector<string> &args) {
int i = 0;
std::istringstream iss(_trim(string(cmd_line)));
for (string s; iss >> s;)
{
args.push_back(s);
++i;
}
return i;
}
SmallShell::SmallShell() {
}
SmallShell::~SmallShell() {
}
Command *SmallShell::CreateCommand(const string &cmd_line, bool is_redirection_command) const {
string cmd_s = _trim(string(cmd_line));
string firstWord = cmd_s.substr(0, cmd_s.find_first_of(" \n"));
if (is_redirection_command)
{
Command *cmd = new ExternalCommand("ls");
cmd->execute();
delete cmd;
} else
{
return new ExternalCommand(cmd_line);
}
}
void SmallShell::executeCommand(const string &cmd_line) {
/** Add spaces before and after >/>> **/
string e_cmd_line = _trim(cmd_line);
bool is_redirection_command = false;
int f_ocu = e_cmd_line.find_first_of('>');
if (f_ocu != string::npos)
{
is_redirection_command = true;
e_cmd_line.insert(f_ocu, " ");
int l_ocu = e_cmd_line.find_last_of('>');
e_cmd_line.insert(l_ocu + 1, " ");
}
Command *cmd = CreateCommand(e_cmd_line, is_redirection_command);
if (cmd->is_built_in()) // redirection is BUILT_IN command
{
// BUILT_IN COMMANDS CAN'T BE STOPPED OR KILLED
cmd->execute();
delete cmd;
} else
{
pid_t pid = fork();
if (pid < 0)
{
perror("smash error: fork failed");
} else if (pid > 0)
{
waitpid(pid, nullptr, WUNTRACED); //CHECKED FINE
delete cmd;
} else
{
setpgrp();
cmd->execute();
delete cmd;
}
}
}
BuiltInCommand::BuiltInCommand(const string &cmd_line) : Command(cmd_line), original_cmd_str(cmd_line) {
}
Command::Command(const string &cmd_line) : cmd_str(cmd_line), num_of_args(_parseCommandLine(cmd_line, args)) {
}
ExternalCommand::ExternalCommand(const string &cmd_line) : Command(cmd_line) {
}
void ExternalCommand::execute() {
string f_cmd = cmd_str;
if (execlp("/bin/bash", "bash", "-c", f_cmd.c_str(), nullptr) < 0)
{
perror("smash error: execv failed");
}
}
#ifndef SMASH_COMMAND_H_
#define SMASH_COMMAND_H_
#include <vector>
#include <stack>
#include <list>
using std::string;
using std::vector;
using std::list;
const std::string WHITESPACE = " \n\r\t\f\v";
extern std::string PROMPT;
class Command
{
public:
string cmd_str;
vector<string> args;
int num_of_args = 0;
virtual bool is_built_in() = 0;
Command(const string &cmd_line);
virtual ~Command() {
}
virtual void execute() = 0;
//virtual void prepare();
//virtual void cleanup();
};
class BuiltInCommand : public Command
{
public:
string original_cmd_str;
bool is_built_in() override {
return true;
}
BuiltInCommand(const string &cmd_line);
virtual ~BuiltInCommand() {
}
};
class ExternalCommand : public Command
{
public:
bool is_built_in() override {
return false;
}
ExternalCommand(const string &cmd_line);
virtual ~ExternalCommand() {
}
void execute() override;
};
class SmallShell
{
public:
static pid_t current_pid;
static string current_cmd;
SmallShell();
Command *CreateCommand(const string &cmd_line, bool is_redirection_command) const;
SmallShell(SmallShell const &) = delete; // disable copy ctor
void operator=(SmallShell const &) = delete; // disable = operator
static SmallShell &getInstance() // make SmallShell singleton
{
static SmallShell instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
~SmallShell();
void executeCommand(const string &cmd_line);
static void route_signal(int sig);
};
#endif //SMASH_COMMAND_H_