naraku9333

csci480_pipe

Mar 24th, 2015
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.99 KB | None | 0 0
  1. /********************************************************************************
  2.    PROGRAM:   Assignment 4
  3.    COURSE:    CSCI-480-1
  4.    AUTHOR:    Sean Vogel
  5.    LOGON ID:  ********
  6.    DUE DATE:  3/24/2015
  7.  
  8.    FUNCTION:  Create a microshell
  9.  
  10.    INPUT:    
  11.  
  12.    OUTPUT:    
  13. ********************************************************************************/
  14. #include <iostream>
  15. #include <string>
  16. #include <cstring>
  17. #include <sstream>
  18. #include <vector>
  19. #include <utility>
  20. #include <iterator>
  21. #include <unistd.h>
  22. #include <sys/types.h>
  23. #include <sys/wait.h>
  24.  
  25. /********************************************************************************
  26. FUNCTION:       get_cmds
  27.  
  28. ARGUMENTS:      const std::string& s - string to split
  29.                 const std::string& delim - delimiter
  30.  
  31. RETURNS:        std::vector<char*> - container of the new strings
  32.  
  33. NOTES:          parses string of commands, spliting string by delimiter
  34. ********************************************************************************/
  35. std::vector<std::string> get_cmds(const std::string& s, const std::string& delim)
  36. {
  37.     std::stringstream ss(s);
  38.     std::vector<std::string> cmds;
  39.     std::string t;
  40.     while(std::getline(ss >> std::ws, t, delim[0]))
  41.     {
  42.         cmds.push_back(t);
  43.         //ss.seekg(ss.tellg() + delim.size() - 1);
  44.         ss >> t;//skip delimiter
  45.     }
  46.     return std::move(cmds);
  47. }
  48.  
  49. /********************************************************************************
  50. FUNCTION:       split_to_cstr
  51.  
  52. ARGUMENTS:      const std::string& - string to split
  53.  
  54. RETURNS:        std::vector<char*> - container of the new strings
  55.  
  56. NOTES:          splits string by whitespace
  57. ********************************************************************************/
  58. std::vector<char*> split_to_cstr(const std::string& s)
  59. {
  60.     std::stringstream ss(s);
  61.  
  62.     std::string t;
  63.     std::vector<char*> args;
  64.  
  65.     while(ss >> t)//split by whitespace
  66.     {
  67.         args.emplace_back(new char[t.length() + 1]);//allocate
  68.         std::strcpy(args.back(), t.c_str());//copy
  69.     }
  70.     return std::move(args);
  71. }
  72.  
  73. /********************************************************************************
  74. FUNCTION:       execute_cmds
  75.  
  76. ARGUMENTS:      int fd[2] - array of file descriptors
  77.                 const std::vector<std::string>& - vector of commands
  78.  
  79. RETURNS:        none
  80.  
  81. NOTES:          fork new process for each command in vector and execute it
  82. ********************************************************************************/
  83. void execute_cmds(int fd[2], const std::vector<std::string>& commands)
  84. {
  85.     for(std::size_t i = 0; i < commands.size(); ++i)
  86.     {
  87.         auto pid = fork();
  88.        
  89.         auto args = split_to_cstr(commands[i]);
  90.         if(pid == 0)
  91.         {
  92.             if(i == 0)//first command
  93.             {
  94.                 if(commands.size() > 1)
  95.                 {
  96.                     close(fd[0]);
  97.                     dup2(fd[1], 1);
  98.                     //close(fd[1]);
  99.                 }
  100.             }
  101.             else if(i == commands.size() - 1)//last command
  102.             {
  103.                 close(fd[1]);
  104.                 dup2(fd[0], 0);
  105.                 //close(fd[0]);
  106.             }
  107.             else//inner commands
  108.             {
  109.                 dup2(fd[0], 0);
  110.                 //close(fd[0]);
  111.                 dup2(fd[1], 1);
  112.                 //close(fd[1]);
  113.             }
  114.             if(execvp(args[0], &args[0]) < 0)
  115.             {
  116.                 std::perror("execvp");
  117.                 exit(EXIT_FAILURE);
  118.             }          
  119.         }
  120.         else if(pid < 0)
  121.         {
  122.             std::perror("fork");
  123.             exit(EXIT_FAILURE);
  124.         }      
  125.     }
  126. }
  127.  
  128. /*void execute_cmd2(int fd[2], const std::string& com)
  129. {
  130.     auto pid = fork();
  131.     auto args = split_to_cstr(com);
  132.     if(pid == 0)
  133.     {
  134.         dup2(fd[0], 0);
  135.         close(fd[1]);
  136.        
  137.         if(execvp(args[0], &args[0]) < 0)
  138.         {
  139.             std::perror("execvp");
  140.             //exit(EXIT_FAILURE);
  141.         }
  142.     }
  143. }*/
  144.  
  145. int main()
  146. {
  147.     std::string prompt("microshell>"),
  148.                 input;
  149.     int fd[2];
  150.  
  151.     while(std::cout << prompt && std::getline(std::cin, input))
  152.     {
  153.         if(pipe(fd) < 0)
  154.         {
  155.             std::perror("pipe");
  156.             exit(EXIT_FAILURE);
  157.         }
  158.  
  159.         std::vector<std::string> commands(get_cmds(input, "||"));
  160.  
  161.         execute_cmds(fd, commands);
  162.  
  163.         close(fd[0]);
  164.         close(fd[1]);
  165.  
  166.         //wait for children to finish
  167.         int pid, status;
  168.         while ((pid = wait(&status)) != -1) ;
  169.             //std::cerr <<  "process " << pid << " exits with " << WEXITSTATUS(status) << std::endl;
  170.     }
  171. }
Advertisement
Add Comment
Please, Sign In to add comment