Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdlib>
- #include <cstring>
- #include <cerrno>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string>
- #include <iostream>
- #include <sys/wait.h>
- #include <stdlib.h>
- using namespace std;
- extern char ** environ; //environmental variables
- char * result[100]; //used to store user input
- bool wasNotBuiltIn = true; //used to determine if you call execute or not
- int exitStatus = 0; //stores the last process's exit status
- //converts the string the user inputs to an array of characters
- char ** convert(string s)
- {
- char * cstr = new char [s.length()+1];
- strcpy (cstr, s.c_str());
- // cstr now contains a c-string copy of str
- int counter = 0;
- char * p = strtok (cstr," ");
- while (p!=0)
- {
- result[counter] = p;
- p = std::strtok(NULL," ");
- counter++;
- }
- return result;
- }
- //checks if there is at least one pipe
- bool checkPipes(char ** c)
- {
- int count = 0;
- while(result[count] != nullptr)
- {
- string pipe = "|";
- if((strcmp(result[count], pipe.c_str())) == 0)
- return true;
- count++;
- }
- return false;
- }
- //executes the user's input if it is not a builtin command
- void execute(char ** c)
- {
- pid_t pid;
- int status;
- //make child process
- if ((pid = fork()) < 0)
- {
- printf("*** ERROR: forking child process failed\n");
- exit(1);
- }
- //only in child
- else if (pid == 0)
- {
- //executes the command or prints error
- if (execvp(*c, c) < 0)
- {
- printf("*** ERROR: exec failed\n");
- exit(1);
- }
- }
- //only in parent
- else
- {
- //waiting for child to finish
- while (wait(&status) != pid);
- }
- //setting exitStatus to the exit status of last process
- exitStatus = status;
- }
- //deletes pipes
- void close_pipe(int pipefd [2]) {
- if (close(pipefd[0]) == -1) {
- perror("close");
- exit(EXIT_FAILURE);
- } // if
- if (close(pipefd[1]) == -1) {
- perror("close");
- exit(EXIT_FAILURE);
- } // if
- } // close_pipe
- //execute logic if there are pipes
- void executePipes(char ** c)
- {
- int pipefd [2];
- int pid;
- // create pipe
- if (pipe(pipefd) == -1)
- {
- perror("pipe");
- } // if
- // create first child
- if ((pid = fork()) == -1) {
- perror("fork");
- } else if (pid == 0) {
- if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
- perror("dup2");
- } // if
- close_pipe(pipefd);
- char ** args = new char * [3];
- args[0] = strdup(c[0]);
- args[1] = strdup(c[1]);
- args[2] = nullptr;
- execvp(args[0], args);
- perror("execvp");
- for (int i = 0; i < 3; ++i) free(args[i]);
- delete[] args;
- exit(EXIT_FAILURE);
- } // if
- // create second child
- if ((pid = fork()) == -1) {
- perror("fork");
- } else if (pid == 0) {
- if (dup2(pipefd[0], STDIN_FILENO) == -1) {
- perror("dup2");
- } // if
- close_pipe(pipefd);
- char ** args;
- if(c[4] == nullptr)
- {
- args = new char * [2];
- args[0] = strdup(c[3]);
- args[1] = nullptr;
- }
- else
- {
- args = new char * [3];
- args[0] = strdup(c[3]);
- args[1] = strdup(c[4]);
- args[2] = nullptr;
- }
- execvp(args[0], args);
- perror("execvp");
- for (int i = 0; i < 2; ++i) free(args[i]);
- delete[] args;
- exit(EXIT_FAILURE);
- } // if
- close_pipe(pipefd);
- // wait on last child
- waitpid(pid, nullptr, 0);
- }
- //creates the prompt, contains builtin logic, and calls the other two methods
- int main()
- {
- //user's input
- string line;
- //prompt logic
- string homeDir = getenv("HOME");
- string presentDir = getenv("PWD");
- string toPrint;
- if(strcmp(homeDir.c_str(), presentDir.substr(0, homeDir.length()).c_str()) == 0)
- {
- toPrint = "~" + presentDir.substr(homeDir.length(), presentDir.length());
- }
- else
- {
- toPrint = presentDir;
- }
- //looping prompt until user exits
- label:
- while(printf("1730sh:%s$ ", toPrint.c_str()) && getline(cin, line))
- {
- convert(line);
- //built in commands
- if(result[0] == nullptr)
- {
- goto label;
- }
- //exit
- string exit = "exit";
- if(strcmp(result[0],exit.c_str()) == 0)
- {
- //user just typed exit
- //return exit status of last executed process
- if(result[1] == nullptr)
- {
- return exitStatus;
- }
- //user typed exit and an exit status
- //return the exit status the user entered
- else
- {
- char * ep;
- return (int)strtol(result[1], &ep, 10);
- }
- }
- //help
- string help = "help";
- string cd = "cd";
- if(strcmp(result[0],help.c_str()) == 0)
- {
- //user typed just help
- //print info about all the builtin commands
- if(result[1] == nullptr)
- {
- cout << "Built-In Commands" << endl;
- cout << "cd [PATH] - Change the current directory to PATH. The environmental variable HOME is the default PATH." << endl;
- cout << "exit [N] - Cause the shell to exit with a status of N. If N is omitted, the exit status is that of the last job executed." << endl;
- cout << "help - Display helpful information about builtin commands." << endl;
- }
- //user typed help and a specific command
- //give info about that command
- else
- {
- if(strcmp(result[1],cd.c_str()) == 0)
- {
- cout << "Built-In Command " << result[1] << endl;
- cout << "cd [PATH] - Change the current directory to PATH. The environmental variable HOME is the default PATH." << endl;
- }
- else if(strcmp(result[1],exit.c_str()) == 0)
- {
- cout << "Built-In Command " << result[1] << endl;
- cout << "exit [N] - Cause the shell to exit with a status of N. If N is omitted, the exit status is that of the last job executed." << endl;
- }
- else if(strcmp(result[1],help.c_str()) == 0)
- {
- cout << "Built-In Command " << result[1] << endl;
- cout << "help - Display helpful information about builtin commands." << endl;
- }
- else
- {
- cout << "That built-in command does not exist." << endl;
- }
- }
- wasNotBuiltIn = false;
- }
- //cd
- if(strcmp(result[0],cd.c_str()) == 0)
- {
- //if just cd, return to home directory
- if(result[1] == nullptr)
- {
- chdir(getenv("HOME"));
- }
- //otherwise, change to target directory
- else
- {
- chdir(result[1]);
- }
- //changing prompt logic
- homeDir = getenv("HOME");
- presentDir = get_current_dir_name();
- if(strcmp(homeDir.c_str(), presentDir.substr(0, homeDir.length()).c_str()) == 0)
- {
- toPrint = "~" + presentDir.substr(homeDir.length(), presentDir.length());
- }
- else
- {
- toPrint = presentDir;
- }
- wasNotBuiltIn = false;
- }
- //if it wasn't a built in command, execute
- if(checkPipes(result))
- {
- executePipes(result);
- }
- else if(wasNotBuiltIn)
- {
- execute(result);
- }
- wasNotBuiltIn = true;
- //resetting the char array
- for(int i = 0; i < 100; i++)
- {
- result[i] = nullptr;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement