daily pastebin goal
25%
SHARE
TWEET

Untitled

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