Advertisement
Guest User

Untitled

a guest
Mar 29th, 2017
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.98 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 <errno.h>
  13. #include <stdlib.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <unistd.h>
  17. #include <fcntl.h>
  18. #include <string.h>
  19.  
  20. extern int obtain_order(); /* See parser.y for description */
  21.  
  22. int main(void)
  23. {
  24. char ***argvv;
  25. int command_counter;
  26. int num_commands;
  27. int args_counter;
  28. char *filev[3];
  29. int bg;
  30. int ret;
  31.  
  32. setbuf(stdout, NULL); /* Unbuffered */
  33. setbuf(stdin, NULL);
  34.  
  35. /* Save copies of standard input, output, error */
  36. int stdincopy = dup(0);
  37. int stdoutcopy = dup(1);
  38. int stderrcopy = dup(2);
  39.  
  40. /* Save environmental variable for mycalc */
  41. char AccLocal = '0';
  42. setenv("Acc", &AccLocal, 1);
  43.  
  44. while (1)
  45. {
  46. fprintf(stderr, "%s", "msh> "); /* Prompt */
  47. ret = obtain_order(&argvv, filev, &bg);
  48. if (ret == 0) {
  49. break; /* EOF */
  50. }
  51. if (ret == -1) continue; /* Syntax error */
  52. num_commands = ret - 1; /* Line */
  53. if (num_commands == 0) continue; /* Empty line */
  54.  
  55. /*
  56. * THE PART THAT MUST BE REMOVED STARTS HERE
  57. * THE FOLLOWING LINES ONLY GIVE AN IDEA OF HOW TO USE THE STRUCTURES
  58. * argvv AND filev. THESE LINES MUST BE REMOVED.
  59. */
  60.  
  61. /* Checks if command given is an internal command: either mycalc or mybak and executes accordingly */
  62. if (!strcmp(argvv[0][0], "mycalc")) {
  63. mycalc(argvv[0]);
  64. continue;
  65. }
  66. else if (!strcmp(argvv[0][0], "mybak")) {
  67. mybak(argvv[command_counter][1], argvv[command_counter][2]);
  68. continue;
  69. }
  70.  
  71. /* Otherwise, we know the command / command sequence is non-internal and we prepare to execute it through children of the minishell process by creating pipes:
  72. */
  73.  
  74. // Creates a pipe for use between potential 1st and 2nd command
  75. int prev[2];
  76. pipe(prev);
  77.  
  78. // Creates a pipe for use between potential 2nd and 3rd command
  79. int seq[2];
  80. pipe(seq);
  81.  
  82. for (command_counter = 0; command_counter < num_commands; command_counter++)
  83. {
  84.  
  85. int pid;
  86. int status;
  87. int fd0, fd1, fd2;
  88. int s;
  89.  
  90. // Creates a child process spawned off the minishell such that each command in a command sequence is executed by its own child process of the minishell
  91. pid = fork();
  92.  
  93. switch(pid) {
  94. case -1: // Reached if fork produced an error (in which case pid = -1 because fork() would've returned -1
  95. perror("Error in fork");
  96. exit(-1);
  97. case 0: // Reached if currently the child process is executing, because fork() returns 0 to the child
  98.  
  99. /* Redirection of error: */
  100. // If error file specified, standard error gets closed and error output gets redirected to the file specified by duplicating the reference at the specified file descriptor to the standard error's reference.
  101. if (filev[2] != NULL){ // ERR
  102. if ((fd2 = open(filev[2], O_CREAT| O_WRONLY, 0666)) < 0) {
  103. perror("Can't open file");
  104. exit(errno);
  105. } else {
  106. close(2);
  107. dup(fd2);
  108. }
  109. }
  110.  
  111. /* Redirection of input: */
  112. // 1) If first command in sequence, input gets redirected from an input file if specified, otherwise will just keep standard input. To redirect, closes standard input file and duplicates the reference at the specified file descriptor to standard input's reference.
  113. if (command_counter == 0) {
  114. if (filev[0] != NULL){
  115. if ((fd0 = open(filev[0], O_RDONLY)) < 0) {
  116. perror("Can't open file");
  117. exit(errno);
  118. } else {
  119. close(0);
  120. dup(fd0);
  121. }
  122. }
  123. }
  124. // 2) If 2nd command in the sequence, input gets redirected from a pipe linked to the output of the 1st command in the sequence. To redirect, closes standard input file and duplicates the reference at the file descriptor of the pipe read end to standard input's reference.
  125. else if (command_counter == 1) {
  126. close(0);
  127. dup(prev[0]);
  128. }
  129. // 3) If 3rd command in the sequence, input gets redirected from a pipe linked to the output of the 2nd command in the sequence. To redirect, closes standard input file and duplicates the reference at the file descriptor of the pipe read end to standard input's reference.
  130. else {
  131. close(0);
  132. dup(seq[0]);
  133. }
  134.  
  135.  
  136. /* Redirection of output: */
  137. // 1) If last command in sequence, output gets redirected to an output file if specified, otherwise will just keep standard output. To redirect, closes standard output file and duplicates the reference at the specified file descriptor to standard output's reference.
  138. if (command_counter == num_commands - 1) {
  139. if (filev[1] != NULL){
  140. if ((fd1 = open(filev[1], O_CREAT | O_WRONLY, 0666)) < 0) {
  141. perror("Can't open file");
  142. exit(errno);
  143. } else {
  144. close(1);
  145. dup(fd1);
  146. }
  147. }
  148. }
  149. // 2) If 1st command in the sequence, output gets redirected to a pipe linked to the input to be read by the 2nd command in the sequence. To redirect, closes standard output file and duplicates the reference at the file descriptor of the pipe write end to standard output's reference.
  150. else if (command_counter == 0) {
  151. close(prev[0]);
  152. close(1);
  153. dup(prev[1]);
  154. }
  155. // 3) If 2nd command in the sequence, output gets redirected to a pipe linked to the input to be read by the 3rd command in the sequence. To redirect, closes standard output file and duplicates the reference at the file descriptor of the pipe write end to standard output's reference.
  156. else {
  157. close(seq[0]);
  158. close(1);
  159. dup(seq[1]);
  160. }
  161.  
  162. // Now that all input / output has been redirected appropriately, the command gets executed where the command name is referenced by argvv[command_counter][0], and all the arguments for that command are referenced by argvv[command_counter]. If and only if command is not properly executed, perror will execute and print the error from the execution. The child exits with the error status returned to the parent (in errno).
  163. execvp(argvv[command_counter][0], argvv[command_counter]);
  164. perror("Error in exec");
  165. exit(errno);
  166.  
  167. default: // Reached if currently the parent minishell process is executing, because fork() returns a non-zero integer representing the child PID
  168.  
  169. /* If background command */
  170. if (bg) {
  171. waitpid(pid, &status, WNOHANG); // If background, parent waits for the child (to kill it appropriately when finished so no zombie processes are left), but without hanging so that the minishell still functions immediately after background command is requested
  172. if (command_counter == num_commands -1) {
  173. printf("[%d]\n", pid);
  174. }
  175. } else { // If not background, parent waits for the child (to kill it appropriately when finished so no zombie processes are left), and is blocked until child finishes execution.
  176. while(wait(&status) != pid);
  177. }
  178. // Parent closes all write ends of pipes used by its children so that sequential children can read from the read ends of such pipes
  179. close(prev[1]);
  180. if (command_counter == 1) {
  181. close(seq[1]);
  182. }
  183. // Restore standard input, output, error for the next command line
  184. if (command_counter == num_commands -1) {
  185. dup2(stdincopy, 0);
  186. dup2(stdoutcopy, 1);
  187. dup2(stderrcopy, 2);
  188. }
  189.  
  190. }
  191.  
  192. }
  193.  
  194.  
  195. /*
  196. * END OF THE PART TO BE REMOVED
  197. */
  198.  
  199. } //fin while
  200. return 0;
  201.  
  202. } //end main
  203.  
  204. int mycalc(char *argv[]){
  205. if (!isInt(argv[1]) || !isInt(argv[3])) {
  206. printf("[ERROR] The structure of the command is <operand 1> <add/mod> <operand 2>\n");
  207. return -1;
  208. }
  209.  
  210. int sum, remainder, diff, quotient;
  211.  
  212. /*If the second parameters is equal to "add", add the first and third parameter and store in a sum variable and the environmental variable Acc.*/
  213. if(strcmp(argv[2], "add")==0){
  214. sum= atoi(argv[1]) + atoi(argv[3]);
  215. char stringAcc[30];
  216. sprintf(stringAcc, "%d", atoi(getenv("Acc")) + sum);
  217. setenv("Acc", stringAcc, 1);
  218. //Acc= *getenv(&Acc) + sum;
  219. printf("[OK] %d + %d = %d; Acc %s\n", atoi(argv[1]), atoi(argv[3]), sum, getenv("Acc"));
  220. return 0;
  221. }
  222. /*If the second parameter is equal to "mod," calculate the modulo using parameter 1 as the dividend and parameter 2 as the divisor.*/
  223. else if(strcmp(argv[2], "mod")==0){
  224. remainder = atoi(argv[1]) % atoi(argv[3]);
  225. diff = atoi(argv[1]) - remainder;
  226. quotient = diff / atoi(argv[3]);
  227. printf("[OK] %d %% %d = %d * %d + %d\n", atoi(argv[1]), atoi(argv[3]), atoi(argv[3]), quotient, remainder);
  228.  
  229. return 0;
  230. }
  231. /*Otherwise print an error message and return -1. */
  232. else {
  233. perror("[ERROR] The structure of the command is <operand 1> <add/mod> <operand 2>\n");
  234. exit(1);
  235. }
  236. }
  237.  
  238. int mybak(char file[], char directory[]) {
  239. char buf[1024];
  240. int fd, fd2, n;
  241.  
  242. /*If there are not 2 parameters, print an error message.*/
  243. /*if(argc != 2) {
  244. printf("[ERROR] The structure of the command is mybak <original file> <output directory>");
  245. return -1;
  246. }*/
  247.  
  248. /*If the value of the file descriptor returned from opening the given file is a negative integer, we print an error message and return -1 */
  249. if ((fd=open(file,O_RDONLY,0666))<0){
  250. perror("Error opening original file\n");
  251. return -1;
  252. }
  253.  
  254. /*If the value of the file descriptor returned from opening the new file is a negative integer, we print an error message and return -1 */
  255. if ((fd2=creat(strcat(directory, file),O_TRUNC))<0){
  256. perror("[ERROR] Error opening the copied file\n");
  257. return -1;
  258. }
  259.  
  260.  
  261. /* The program will read the contents of the file into the immediate buffer, buf, of 1024 bytes. Standard output is closed and the contents of the buffer will be written to the new file.*/
  262. close(0);
  263. while ((n=read(fd,buf,1024))>0){
  264. write(fd2, buf, n);
  265. }
  266.  
  267. /*If read is unsuccessful, n will have been set to -1, and the loop will be exited out of. So, we print an error message and return -1*/
  268. if (n<0) {
  269. perror("[ERROR] Error opening the copied file\n");
  270. return -1;
  271. }
  272. /*Otherwise, we print a message that the file has been copied successfully to the new directory and return 0.*/
  273. else {
  274. printf("[OK] Copy has been successful between <original filename> to the directory <output directory>.\n");
  275. return 0;
  276. }
  277. }
  278.  
  279. int isInt(char param[]){
  280. if (param == NULL) {
  281. return 0;
  282. }
  283. int index;
  284. for(index=0; param[index]!= '\0'; index++){
  285. if(!isdigit(param[index])){
  286. if(param[index]!='-'){
  287. return 0;
  288. }
  289. }
  290.  
  291. }
  292. return 1;
  293. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement