Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********************************************************************************
- PROGRAM: Assignment 4
- COURSE: CSCI-480-1
- AUTHOR: Sean Vogel
- LOGON ID: ********
- DUE DATE: 3/24/2015
- FUNCTION: Create a microshell
- INPUT:
- OUTPUT:
- ********************************************************************************/
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <sstream>
- #include <vector>
- #include <utility>
- #include <iterator>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- /********************************************************************************
- FUNCTION: get_cmds
- ARGUMENTS: const std::string& s - string to split
- const std::string& delim - delimiter
- RETURNS: std::vector<char*> - container of the new strings
- NOTES: parses string of commands, spliting string by delimiter
- ********************************************************************************/
- std::vector<std::string> get_cmds(const std::string& s, const std::string& delim)
- {
- std::stringstream ss(s);
- std::vector<std::string> cmds;
- std::string t;
- while(std::getline(ss >> std::ws, t, delim[0]))
- {
- cmds.push_back(t);
- //ss.seekg(ss.tellg() + delim.size() - 1);
- ss >> t;//skip delimiter
- }
- return std::move(cmds);
- }
- /********************************************************************************
- FUNCTION: split_to_cstr
- ARGUMENTS: const std::string& - string to split
- RETURNS: std::vector<char*> - container of the new strings
- NOTES: splits string by whitespace
- ********************************************************************************/
- std::vector<char*> split_to_cstr(const std::string& s)
- {
- std::stringstream ss(s);
- std::string t;
- std::vector<char*> args;
- while(ss >> t)//split by whitespace
- {
- args.emplace_back(new char[t.length() + 1]);//allocate
- std::strcpy(args.back(), t.c_str());//copy
- }
- return std::move(args);
- }
- /********************************************************************************
- FUNCTION: execute_cmds
- ARGUMENTS: int fd[2] - array of file descriptors
- const std::vector<std::string>& - vector of commands
- RETURNS: none
- NOTES: fork new process for each command in vector and execute it
- ********************************************************************************/
- void execute_cmds(int fd[2], const std::vector<std::string>& commands)
- {
- for(std::size_t i = 0; i < commands.size(); ++i)
- {
- auto pid = fork();
- auto args = split_to_cstr(commands[i]);
- if(pid == 0)
- {
- if(i == 0)//first command
- {
- if(commands.size() > 1)
- {
- close(fd[0]);
- dup2(fd[1], 1);
- //close(fd[1]);
- }
- }
- else if(i == commands.size() - 1)//last command
- {
- close(fd[1]);
- dup2(fd[0], 0);
- //close(fd[0]);
- }
- else//inner commands
- {
- dup2(fd[0], 0);
- //close(fd[0]);
- dup2(fd[1], 1);
- //close(fd[1]);
- }
- if(execvp(args[0], &args[0]) < 0)
- {
- std::perror("execvp");
- exit(EXIT_FAILURE);
- }
- }
- else if(pid < 0)
- {
- std::perror("fork");
- exit(EXIT_FAILURE);
- }
- }
- }
- /*void execute_cmd2(int fd[2], const std::string& com)
- {
- auto pid = fork();
- auto args = split_to_cstr(com);
- if(pid == 0)
- {
- dup2(fd[0], 0);
- close(fd[1]);
- if(execvp(args[0], &args[0]) < 0)
- {
- std::perror("execvp");
- //exit(EXIT_FAILURE);
- }
- }
- }*/
- int main()
- {
- std::string prompt("microshell>"),
- input;
- int fd[2];
- while(std::cout << prompt && std::getline(std::cin, input))
- {
- if(pipe(fd) < 0)
- {
- std::perror("pipe");
- exit(EXIT_FAILURE);
- }
- std::vector<std::string> commands(get_cmds(input, "||"));
- execute_cmds(fd, commands);
- close(fd[0]);
- close(fd[1]);
- //wait for children to finish
- int pid, status;
- while ((pid = wait(&status)) != -1) ;
- //std::cerr << "process " << pid << " exits with " << WEXITSTATUS(status) << std::endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment