Advertisement
Guest User

Untitled

a guest
Mar 29th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.43 KB | None | 0 0
  1. /*-
  2. * msh.c
  3. *
  4. * Minishell C source
  5. * Show how to use "obtain_order" input interface function
  6. *
  7. * THIS FILE IS TO BE MODIFIED
  8. */
  9.  
  10. #include <stddef.h> /* NULL */
  11. #include <stdio.h> /* setbuf, printf */
  12. #include <stdlib.h>
  13. #include <fcntl.h>
  14. #include <unistd.h>
  15. #include <stdbool.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18.  
  19. extern int obtain_order(); /* See parser.y for description */
  20.  
  21. void redirect_standards(char *filev[3]){
  22. int fd;
  23. if (filev[0] != NULL){
  24. fd = open(filev[0], O_RDONLY);
  25. close(STDIN_FILENO);
  26. dup(fd);
  27. close(fd);
  28. }
  29. if (filev[1] != NULL){
  30. fd = open(filev[1], O_CREAT| O_WRONLY, 0666);
  31. close(STDOUT_FILENO);
  32. dup(fd);
  33. close(fd);
  34. }
  35. if (filev[2] != NULL){
  36. fd = open(filev[2], O_CREAT| O_WRONLY, 0666);
  37. close(STDERR_FILENO);
  38. dup(fd);
  39. close(fd);
  40. }
  41. }
  42.  
  43. void restore_standards(char *filev[3], int standards[3]){
  44. if (filev[0] != NULL){
  45. int savein = standards[0];
  46. dup2(savein, STDIN_FILENO);
  47. close(savein);
  48. }
  49. if (filev[1] != NULL){
  50. int saveout = standards[1];
  51. dup2(saveout, STDOUT_FILENO);
  52. close(saveout);
  53. }
  54. if (filev[2] != NULL){
  55. int saveerr = standards[2];
  56. dup2(saveerr, STDERR_FILENO);
  57. close(saveerr);
  58. }
  59. }
  60.  
  61. bool check_operand(char *operand){
  62. if (operand == NULL)
  63. return false;
  64. int i = 0;
  65. while (operand[i] != '\0'){
  66. if (isdigit(operand[i] - '0') != 0){
  67. printf("%d\n", operand[i] - '0');
  68. return false;
  69. }
  70. i++;
  71. }
  72. return true;
  73. }
  74.  
  75. bool check_command(char operand1[], char operand2[], char operator[]){
  76. if (check_operand(operand1) == 0 || check_operand(operand2) == 0 || (strcmp(operator, "add\0") !=0 && strcmp(operator, "mod\0") != 0)){
  77. char * errmsg = "[ERROR] The structure of the command is <operand 1><add/mod><operand 2>\n";
  78. write(2, errmsg, strlen(errmsg));
  79. return false;
  80. }
  81. return true;
  82. }
  83.  
  84. void my_calc(char ***argvv, int * acc){
  85. char msg[1024]; //IDK WHAT TO SET THIS AS BC IDK HOW LONG THE MSG WILL BE
  86. char * op1str = argvv[0][1];
  87. char * op2str = argvv[0][3];
  88. char * operator = argvv[0][2];
  89.  
  90. if (check_command(op1str, op2str, operator)){
  91. int operand1 = atoi(op1str);
  92. int operand2 = atoi(op2str);
  93.  
  94. if (strcmp(operator, "add\0") == 0){
  95. int sum = operand1 + operand2;
  96. (*acc) += sum;
  97. sprintf(msg, "[OK] %d + %d = %d; Acc %d\n", operand1, operand2, sum, *acc);
  98. write(1, msg, strlen(msg));
  99. }
  100. if (strcmp(operator, "mod\0") == 0){
  101. int mod = operand1 % operand2;
  102. int div = operand1 / operand2;
  103. sprintf(msg, "[OK] %d %% %d = %d * %d + %d\n", operand1, operand2, operand2, div, mod);
  104. write(1, msg, strlen(msg));
  105. }
  106. }
  107. }
  108.  
  109. int main(void)
  110. {
  111. char ***argvv;
  112. int command_counter;
  113. int num_commands;
  114. int args_counter;
  115. char *filev[3];
  116. int bg;
  117. int ret;
  118. int standards[3];
  119. int Acc = 0;
  120. int status;
  121. int pid;
  122.  
  123. setbuf(stdout, NULL); /* Unbuffered */
  124. setbuf(stdin, NULL);
  125.  
  126. while (1)
  127. {
  128. fprintf(stderr, "%s", "msh> "); /* Prompt */
  129. ret = obtain_order(&argvv, filev, &bg);
  130. if (ret == 0) break; /* EOF */
  131. if (ret == -1) continue; /* Syntax error */
  132. num_commands = ret - 1; /* Line */
  133. if (num_commands == 0) continue; /* Empty line */
  134.  
  135. /*
  136. * THE PART THAT MUST BE REMOVED STARTS HERE
  137. * THE FOLLOWING LINES ONLY GIVE AN IDEA OF HOW TO USE THE STRUCTURES
  138. * argvv AND filev. THESE LINES MUST BE REMOVED.
  139. */
  140.  
  141. //SAVE STANDARDS IN CASE REDIRECTED
  142. standards[0] = dup(STDIN_FILENO);
  143. standards[1] = dup(STDOUT_FILENO);
  144. standards[2] = dup(STDERR_FILENO);
  145.  
  146. //REDIRECT STANDARDS IF SPECIFIED
  147. redirect_standards(filev);
  148.  
  149.  
  150. if(strcmp(argvv[0][0], "mycalc\0") == 0){
  151. my_calc(argvv, &Acc);
  152. }
  153. else{
  154.  
  155. int oldp[2];
  156. int newp[2];
  157.  
  158. for(command_counter = 0; command_counter < num_commands; command_counter++){
  159.  
  160. // If not last (or only) command in sequence, make a pipe between current process and next process
  161. if (command_counter < num_commands - 1)
  162. pipe(newp);
  163.  
  164. pid = fork();
  165.  
  166. if (pid == 0){
  167. // If sequence of commands, redirect input/output between processes of each command
  168. if (num_commands > 1) {
  169. // If first command in sequence, close read end of next pipe because only writing to it, and
  170. // redirect standard output to write end of next pipe
  171. if(command_counter == 0){
  172. close(newp[0]);
  173. dup2(newp[1], STDOUT_FILENO);
  174. }
  175. // If in between command, close read end of next pipe because only writing to it, and
  176. // redirect standard input to read end from last pipe and standard output to write end of next pipe
  177. else if (command_counter > 0 && command_counter < num_commands-1){
  178. close(newp[0]);
  179. dup2(oldp[0], STDIN_FILENO);
  180. dup2(newp[1], STDOUT_FILENO);
  181.  
  182. }
  183. // If in last command, redirect standard read to read from last pipe, and
  184. // don't redirect standard output to anything
  185. else{
  186. dup2(oldp[0], STDIN_FILENO);
  187. }
  188. }
  189.  
  190. if ((execvp(argvv[command_counter][0], argvv[command_counter]) < 0)){
  191. perror("ERROR EXECUTING COMMAND");
  192. exit(-1);
  193. }
  194. }
  195.  
  196. // If sequence of commands, appropriately manage open file descriptors in parents for pipes in parent process
  197. if (num_commands > 1){
  198. // If first command in sequence, close write end of next pipe because process of next command will only read from the pipe, never write to it, and
  199. // save next pipe for use by next process
  200. if(command_counter == 0){
  201. close(newp[1]);
  202. oldp[0] = newp[0];
  203. oldp[1] = newp[1];
  204. }
  205. // If in between command, close read end of last pipe because no longer need it, since already passed off to child process, and
  206. // close write end of next pipe because process of next command will only read from it, never write to it, and
  207. // save next pipe for use by next process
  208. else if (command_counter > 0 && command_counter < num_commands-1){
  209. close(oldp[0]);
  210. close(newp[1]);
  211. oldp[0] = newp[0];
  212. oldp[1] = newp[1];
  213. }
  214. // If last command in sequence, close read and write end of last pipe because have already passed it off to child process and don't need it
  215. else{
  216. close(oldp[0]);
  217. close(oldp[1]);
  218. }
  219. }
  220.  
  221. //BACKGROUND CHECK
  222. if (bg == 0)
  223. while(wait(&status) != pid);
  224. else{
  225. waitpid(pid, &status, WNOHANG);
  226. if (command_counter == num_commands -1)
  227. printf("[%d]\n", pid);
  228. }
  229. }
  230.  
  231. }
  232.  
  233. //RESTORE STANDARDS
  234. restore_standards(filev, standards);
  235.  
  236.  
  237.  
  238. /*
  239. * END OF THE PART TO BE REMOVED
  240. */
  241.  
  242. } //fin while
  243.  
  244. return 0;
  245.  
  246. } //end main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement