parser works. piping wip.

This commit is contained in:
Ben Harris 2016-11-11 21:49:32 -05:00
parent 4a3ed941b0
commit d628315a5f
5 changed files with 148 additions and 127 deletions

187
bish.cc
View File

@ -25,7 +25,6 @@ int main(int argc, char **argv){
stringstream prompt;
static char* line = (char*)NULL;
vector<string> path = split(getenv("PATH"), ':');
const char *homedir;
if ((homedir = getenv("HOME")) == NULL) {
@ -42,7 +41,8 @@ int main(int argc, char **argv){
}
while ("bish") {
int done = 0;
while (!done) {
prompt.str("");
prompt << "\e[34mbish:\e[92m" << get_current_dir_name() << "\e[34m:$\e[0m ";
@ -52,108 +52,129 @@ int main(int argc, char **argv){
if (strcmp(line, "") == 0) continue;
if (line && *line) add_history (line);
// char **args = v_to_cpp(split(line));
// parse line
// handle multiple commands w/ semicolon
vector<string> wfwe = split(line, ';');
for (auto it: wfwe) {
command *cmd = parse(split(it.c_str()));
// print_cmd(cmd);
// debug info
print_cmd(cmd);
cout << "-----------------------------" << endl;
// clear line var
free(line);
line = (char*)NULL;
// COMMANDS that do something with the line before fork/exec
if (strcmp(cmd->cmds[0]->args[0], "!") == 0) {
line = history_get(where_history())->line;
cout << line << endl;
cmd = parse(split(line));
if (cmd->cmds[0].vargs[0] == "exit") {
done = 1;
break;
}
if (cmd->cmds[0].vargs[0] == "cd") {
if (cmd->cmds[0].vargs[1] == "") {
if (chdir(homedir) < 0) perror("chdir");
} else {
if (chdir(cmd->cmds[0].vargs[1].c_str()) < 0) perror("chdir");
}
}
else if (strcmp(cmd->cmds[0]->args[0], ".") == 0 || strcmp(cmd->cmds[0]->args[0], "source") == 0) {
int dotsrcfile = open(cmd->cmds[0]->args[1], O_RDONLY);
if (dotsrcfile < 0) {
perror("dotsrcfile");
continue;
}
// do the thing to read the files
for (auto curr: cmd->cmds) {
// else { // do fork/exec
pid_t kidpid = fork();
// fork error
if (kidpid < 0) {
perror("fork");
return -1;
}
// run it
// also check the path for things
else if (kidpid == 0){
int infd = 0, outfd = 1;
// io redirection
if (curr.outfile != "") {
outfd = open(curr.outfile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
if (outfd < 0) {
perror("outfile");
exit(0);
}
}
if (curr.infile != "") {
infd = open(curr.infile.c_str(), O_RDONLY);
if (infd < 0) {
perror("infile");
exit(0);
}
}
bishexec(&curr, infd, outfd);
exit(1);
} // end child
// parent waits for kid to die
else {
int status;
if (!cmd->background){
do {
if (waitpid(kidpid, &status, WUNTRACED | WCONTINUED) == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status)) {
cout << "(" << WEXITSTATUS(status) << "):";
} else if (WIFSIGNALED(status)) {
cout << endl << "killed by signal " << WTERMSIG(status) << endl;
} else if (WIFSTOPPED(status)) {
cout << endl << "stopped by signal " << WSTOPSIG(status) << endl;
} else if (WIFCONTINUED(status)) {
cout << endl << "continued" << endl;
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
} // end parent
// } // end fork/exec stuff
}
// COMMANDS that do something with the line before fork/exec
// if (strcmp(cmd->cmds[0]->args[0], "!") == 0) {
// line = history_get(where_history())->line;
// cout << line << endl;
// cmd = parse(split(line));
// }
// else if (strcmp(cmd->cmds[0]->args[0], ".") == 0 || strcmp(cmd->cmds[0]->args[0], "source") == 0) {
// int dotsrcfile = open(cmd->cmds[0]->args[1], O_RDONLY);
// if (dotsrcfile < 0) {
// perror("dotsrcfile");
// continue;
// }
// // do the thing to read the files
// }
// COMMANDS that skip fork/exec
// http://www.linuxquestions.org/questions/programming-9/making-a-c-shell-775690/
if (strcmp(cmd->cmds[0]->args[0], "exit") == 0) break;
// if (strcmp(cmd->cmds[0]->args[0], "exit") == 0) break;
// handle chdir
else if (strcmp(cmd->cmds[0]->args[0], "cd") == 0) {
if (cmd->cmds[0]->args[1] == NULL) {
if (chdir(homedir) < 0) perror("chdir");
}
else {
if (chdir(cmd->cmds[0]->args[1]) < 0) perror("chdir");
}
}
// else if (strcmp(cmd->cmds[0]->args[0], "cd") == 0) {
// if (cmd->cmds[0]->args[1] == NULL) {
// if (chdir(homedir) < 0) perror("chdir");
// }
// else {
// if (chdir(cmd->cmds[0]->args[1]) < 0) perror("chdir");
// }
// }
// process the line.
else {
// else {
pid_t kidpid = fork();
// fork error
if (kidpid < 0) {
perror("fork");
return -1;
}
// run it
// also check the path for things
else if (kidpid == 0){
int infd = 0, outfd = 1;
// } // end execute area
// io redirection
if (cmd->cmds[0]->outfile != "") {
outfd = open(cmd->cmds[0]->outfile.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
if (outfd < 0) {
perror("outfile");
exit(0);
}
}
if (cmd->cmds[0]->infile != "") {
infd = open(cmd->cmds[0]->infile.c_str(), O_RDONLY);
if (infd < 0) {
perror("infile");
exit(0);
}
}
bishexec(cmd, infd, outfd);
exit(1);
} // end child
// parent waits for kid to die
else {
int status;
if (!cmd->background){
do {
if (waitpid(kidpid, &status, WUNTRACED | WCONTINUED) == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status)) {
cout << "(" << WEXITSTATUS(status) << "):";
} else if (WIFSIGNALED(status)) {
cout << endl << "killed by signal " << WTERMSIG(status) << endl;
} else if (WIFSTOPPED(status)) {
cout << endl << "stopped by signal " << WSTOPSIG(status) << endl;
} else if (WIFCONTINUED(status)) {
cout << endl << "continued" << endl;
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
} // end parent
} // end execute area
// reset args array for the next prompt
delete cmd;

View File

@ -10,65 +10,61 @@ using namespace std;
void print_cmd(command *cmd) {
if (cmd->background) cout << "backgroud: true" << endl;
if (cmd->piping) cout << "piping to: " << cmd->piping << endl;
if (cmd->cmds[0]->infile != "") cout << "infile: " << cmd->cmds[0]->infile << endl;
if (cmd->cmds[0]->outfile != "") cout << "outfile: " << cmd->cmds[0]->outfile << endl;
int i = 0;
for (auto cmd_iter: cmd->cmds) {
if (cmd->background) cout << "backgroud: true" << endl;
cout << "simple_command: " << i++ << endl;
cout << "infile: " << cmd_iter.infile << endl;
cout << "outfile: " << cmd_iter.outfile << endl << endl;
for (auto scmd_iter: cmd_iter.vargs) {
cout << scmd_iter << " ";
}
cout << endl;
}
}
command *parse(vector<string> args) {
command *parseinfo = new command();
bool in_flag = false, out_flag = false;//, piping_flag = false;
vector<vector<string>> cmd;
int num_cmds = 0;
command *parsed_command = new command();
bool in_flag = false, out_flag = false;
simple_command *current_simple = new simple_command();
for (auto it: args) {
if (it == "<") {
for (auto iter: args) {
if (iter == "<") {
in_flag = true;
continue;
}
else if (in_flag) {
in_flag = false;
parseinfo->cmds[num_cmds]->infile = it;
current_simple->infile = iter;
}
else if (it == ">") {
else if (iter == ">") {
out_flag = true;
continue;
}
else if (out_flag) {
out_flag = false;
parseinfo->cmds[num_cmds]->outfile = it;
current_simple->outfile = iter;
}
else if (it == "|") {
// piping_flag = true;
// cmd.push_back();
num_cmds++;
else if (iter == "|") {
parsed_command->cmds.push_back(*current_simple);
delete current_simple;
current_simple = new simple_command();
continue;
}
// else if (piping_flag) {
// // piping_flag = false;
// parseinfo->piping = true;
// }
else if (it == args.back() && it == "&") {
parseinfo->background = true;
else if (iter == args.back() && iter == "&") {
parsed_command->background = true;
}
else {
cmd[num_cmds].push_back(it);
current_simple->vargs.push_back(iter);
}
}
int i = 0;
for (auto it: cmd) {
parseinfo->cmds[i]->args = v_to_cpp(cmd[0]);
}
parseinfo->num_cmds = num_cmds;
return parseinfo;
parsed_command->cmds.push_back(*current_simple);
return parsed_command;
}

View File

@ -9,16 +9,15 @@ using namespace std;
// simple_command struct
struct simple_command {
char** args;
vector<string> vargs;
// char** args;
string infile;
string outfile;
};
// command struct
struct command {
simple_command** cmds;
int num_cmds;
vector<simple_command> cmds;
bool background;
bool piping;
};
// method definitions

View File

@ -8,6 +8,7 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "parse.h"
#include "util_fns.h"
using namespace std;
@ -41,7 +42,8 @@ char** v_to_cpp(vector<string> vargs) {
}
void bishexec(command* cmd, int infd, int outfd) {
void bishexec(simple_command* cmd, int infd, int outfd) {
if (outfd != 1) {
if (dup2(outfd, 1) == -1) {
perror("dup2 outfile");
@ -56,13 +58,16 @@ void bishexec(command* cmd, int infd, int outfd) {
}
// try to run it as is
execvp(cmd->cmds[0]->args[0], cmd->cmds[0]->args);
execvp(cmd->vargs[0].c_str(), v_to_cpp(cmd->vargs));
// search the path
// stringstream searchpath;
// for (auto it: path) {
// searchpath.str("");
// searchpath << it << "/" << cmd->args[0];
// execv(searchpath.str().c_str(), cmd->args);
// vector<string> path = split(getenv("PATH"), ':');
// stringstream curr;
// for (auto iter: path) {
// curr.str("");
// curr << iter << "/" << cmd->vargs[0];
// execv(curr.str().c_str(), v_to_cpp(cmd->vargs));
// }
// nothing found here...
cout << "that's not a command, bish" << endl;

View File

@ -12,6 +12,6 @@ using namespace std;
void ctrlCHandler(int sig);
vector<string> split(const char *str, char c = ' ');
char** v_to_cpp(vector<string> vargs);
void bishexec(command* cmd, int infd, int outfd);
void bishexec(simple_command* cmd, int infd, int outfd);
#endif