Advertisement
Guest User

Untitled

a guest
Apr 10th, 2015
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.29 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement