daily pastebin goal
25%
SHARE
TWEET

Untitled

a guest Apr 10th, 2015 191 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  
  3. Name: Maksim Levental
  4.  
  5. UF ID: 3186-7826
  6.  
  7. Gator ID: mlevental86
  8.  
  9. Discussion Section #: 0556
  10.  
  11. */
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include <wait.h>
  17.  
  18. #define COMMAND_LINE_LENGTH 200
  19. #define COMMAND_LENGTH 10
  20. #define MAX_NUM_ARGS 10
  21. #define MAX_NUM_PIPES 10
  22. /* Breaks the string pointed by str into words and stores them in the arg array*/
  23. int getArguments(char *,char *[]);
  24.  
  25. /* Breaks the string pointed by str into pipes and stores them in the arg array*/
  26. int getPipes(char *,char *[]);
  27.  
  28. /* Reads a line and discards the end of line character */
  29. int getLine(char *str,int max);
  30.  
  31. int numArgs = 0;
  32. /* Simulates a shell, i.e., gets command names and executes them */
  33. int main(int argc, char *argv[])
  34. {
  35.  
  36.   char commandLine[COMMAND_LINE_LENGTH+1];
  37.  
  38.   char *pipes[MAX_NUM_PIPES]; //array len MAX_NUM_PIPES of ptr to char
  39.   int i,j; //for loop vars
  40.  
  41.   printf("Welcome to Extremely Simple Shell\n");
  42.  
  43.   int exit= 0;
  44.  
  45.   loop:
  46.  
  47.   do {
  48.       int status;
  49.       char *temp[MAX_NUM_ARGS];
  50.      
  51.      
  52.       /* Prints the command prompt */
  53.       printf("\n$ ");
  54.      
  55.       /* Reads the command line and stores it in array commandLine */
  56.       getLine(commandLine,COMMAND_LINE_LENGTH+1);
  57.  
  58.       /* The user did not enter any commands */
  59.       if (!strcmp(commandLine,""))
  60.          continue;
  61.      
  62.       /* Breaks the command line into arguments and stores the arguments in arguments array */
  63.       int numPipes = getPipes(commandLine,pipes);
  64.      
  65.      
  66.       char ***arguments; //ptr to array of ptrs each of which is itself a ptr to array of ptrs to char arrays/ptrs (the actual commands)
  67.       arguments = malloc(numPipes * sizeof(char **)); // each element in the first level is a ptr to array of ptrs which each point to the
  68.                                                       // actual commands
  69.                                                      
  70.       // these 2 loops fill an array with the commands in the command line.
  71.       // a pipe string is command string that comes before a pipe or after. if no | in command line numPipes = 1
  72.       // array has 1 row for each pipe string. and then each entry in the row for the actual command words
  73.  
  74.       for(i = 0; i < numPipes; i++){
  75.        
  76.         // pipe string is passed to getArguments, tokenized, then individual words fill temp. temp will then be copied into the arguments array        
  77.         numArgs = getArguments(pipes[i],temp);
  78.         arguments[i] = malloc(numArgs * sizeof(char *)); //each element in the second level pts to a command/arg
  79.        
  80.         for(j = 0; j < numArgs; j++){
  81.        
  82.                 arguments[i][j] = malloc(strlen(temp[j]) * sizeof(char)); // element in the 3rd level is an actual command/array of chars
  83.                 //actual copying of words into argument array happens here
  84.                 strcpy(arguments[i][j], temp[j]);
  85.                
  86.                 //scans the commands in all pipes and terminates the program when the user types exit or quit
  87.                 if (!strcmp(arguments[i][j],"quit") || !strcmp(arguments[i][j],"exit"))
  88.                   return(0);
  89.                        
  90.         }
  91.        
  92.        
  93.       }
  94.      
  95.       // conditional run only if a pipe is used in the command line. otherwise flow goes to 115, standard execvp
  96.       if(numPipes == 2){
  97.               //file descriptor array to be used with sys call pipes
  98.               int fd[2];
  99.               int fd1[2];
  100.               int fd2[2];
  101.               int fd3[2];
  102.               if(pipe(fd) == -1){ perror("pipe error"); return(1);}
  103.                 if(pipe(fd1) == -1){ perror("pipe error"); return(1);}
  104.                 if(pipe(fd2) == -1){ perror("pipe error"); return(1);}
  105.                 if(pipe(fd3) == -1){ perror("pipe error"); return(1);}       
  106.                 //first child, which does the writing to the opened pipe
  107.               if(fork() == 0){
  108.                 //std_out is rerouted to pipe read end
  109.                 dup2(fd[1], STDOUT_FILENO);
  110.                 //both ends of pipe are now closed. read end because it was never meant to be used and write end because it's
  111.                 //re-aliased to std_out
  112.                 close(fd[0]);
  113.                 close(fd[1]);
  114.                 //command is executed using first row of arguments array
  115.                 execvp(arguments[0][0], arguments[0]);
  116.                 perror("execvp failed");
  117.                 return(1);        
  118.              
  119.               }
  120.               //second child, which does the reading
  121.               if(fork() == 0){
  122.                 //std_in is rerouted to read end of the pipe.
  123.                 dup2(fd[0], STDIN_FILENO);
  124.                 dup2(fd1[1],STDOUT_FILENO);
  125.                 //both ends of pipe are now closed. write end because it was never going to be used and read end
  126.                 //because it's re-aliased to std_in
  127.                 close(fd[1]);
  128.                 close(fd[0]);
  129.                 close(fd1[1]);
  130.                 close(fd1[0]);
  131.                 //command is executed using second row of arguments array
  132.                 execvp(arguments[1][0], arguments[1]);
  133.                 perror("execvp failed");
  134.                 return(1);
  135.                
  136.               }
  137.                
  138.         if(fork() == 0){
  139.                 //std_in is rerouted to read end of the pipe.
  140.                 dup2(fd1[0], STDIN_FILENO);
  141.                 //both ends of pipe are now closed. write end because it was never going to be used and read end
  142.                 //because it's re-aliased to std_in
  143.                 close(fd[1]);
  144.                 close(fd[0]);
  145.                 close(fd1[1]);
  146.                 close(fd1[0]);
  147.                 //command is executed using second row of arguments array
  148.                 execvp(arguments[1][0], arguments[1]);
  149.                 perror("execvp failed");
  150.                 return(1);
  151.                
  152.               }
  153.          
  154.               //parent closes both pipe ends and waits for child processes to terminate. go to is used so that command prompt comes
  155.               //back up
  156.               close(fd[1]);
  157.                 close(fd[0]);
  158.                 close(fd1[1]);
  159.                 close(fd1[0]);
  160.                 wait(0);
  161.               wait(0);
  162.               goto loop;
  163.       }
  164.      
  165.       else{
  166.      
  167.               /* Creates a child process */  
  168.               int pid = fork();
  169.              
  170.               switch (pid)
  171.               {
  172.                   case 0: /* Executed by the child process only */
  173.                           execvp(arguments[0][0],arguments[0]);
  174.                           perror("Exec error\n");
  175.                           break;
  176.                   case -1: /* Executed only when the fork system call fails */
  177.                           perror("Fork error\n");
  178.                           break;
  179.                   default: /* Executed by parent process only  */
  180.                           wait(&status);
  181.                           break;        
  182.               }
  183.              
  184.       }
  185.      
  186.   }
  187.   while (1); /* Use int values to represent boolean in C language: 0 denotes false, non-zero denotes true */
  188.  
  189.  
  190.   return 0;
  191. }
  192.  
  193. /* Breaks the string pointed by str into string before pipe and after pipe and stores them in the arg array*/
  194. int getPipes(char *str, char *arg[])
  195. {
  196.      char delimeter[] = "|";
  197.      char *temp = NULL;
  198.      int i=0;
  199.      temp = strtok(str,delimeter);
  200.      while (temp != NULL)
  201.      {
  202.            arg[i++] = temp;                  
  203.            temp = strtok(NULL,delimeter);
  204.      }
  205.      arg[i] = NULL;    
  206.      return i;
  207. }
  208.  
  209.  
  210.  
  211. /* Breaks the string pointed by str into words and stores them in the arg array*/
  212. int getArguments(char *str, char *arg[])
  213. {
  214.      char delimeter[] = " ";
  215.      char *temp = NULL;
  216.      int i=0;
  217.      temp = strtok(str,delimeter);
  218.      while (temp != NULL)
  219.      {
  220.            arg[i++] = temp;                  
  221.            temp = strtok(NULL,delimeter);
  222.      }
  223.      arg[i] = NULL;    
  224.      return i;
  225. }
  226.  
  227. /* Reads a line and discards the end of line character */
  228. int getLine(char *str,int max)
  229. {
  230.     char *temp;
  231.     if ((temp = fgets(str,max,stdin)) != NULL)
  232.     {
  233.        int len = strlen(str);
  234.        str[len-1] = '\0';
  235.        return len-1;
  236.     }  
  237.     else return 0;
  238. }
RAW Paste Data
Top