Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*-
- * msh.c
- *
- * Minishell C source
- * Show how to use "obtain_order" input interface function
- *
- * THIS FILE IS TO BE MODIFIED
- */
- #include <stddef.h> /* NULL */
- #include <stdio.h> /* setbuf, printf */
- #include <stdlib.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdbool.h>
- #include <string.h>
- #include <ctype.h>
- extern int obtain_order(); /* See parser.y for description */
- void redirect_standards(char *filev[3]){
- int fd;
- if (filev[0] != NULL){
- fd = open(filev[0], O_RDONLY);
- close(STDIN_FILENO);
- dup(fd);
- close(fd);
- }
- if (filev[1] != NULL){
- fd = open(filev[1], O_CREAT| O_WRONLY, 0666);
- close(STDOUT_FILENO);
- dup(fd);
- close(fd);
- }
- if (filev[2] != NULL){
- fd = open(filev[2], O_CREAT| O_WRONLY, 0666);
- close(STDERR_FILENO);
- dup(fd);
- close(fd);
- }
- }
- void restore_standards(char *filev[3], int standards[3]){
- if (filev[0] != NULL){
- int savein = standards[0];
- dup2(savein, STDIN_FILENO);
- close(savein);
- }
- if (filev[1] != NULL){
- int saveout = standards[1];
- dup2(saveout, STDOUT_FILENO);
- close(saveout);
- }
- if (filev[2] != NULL){
- int saveerr = standards[2];
- dup2(saveerr, STDERR_FILENO);
- close(saveerr);
- }
- }
- bool check_operand(char *operand){
- if (operand == NULL)
- return false;
- int i = 0;
- while (operand[i] != '\0'){
- if (isdigit(operand[i] - '0') != 0){
- printf("%d\n", operand[i] - '0');
- return false;
- }
- i++;
- }
- return true;
- }
- bool check_command(char operand1[], char operand2[], char operator[]){
- if (check_operand(operand1) == 0 || check_operand(operand2) == 0 || (strcmp(operator, "add\0") !=0 && strcmp(operator, "mod\0") != 0)){
- char * errmsg = "[ERROR] The structure of the command is <operand 1><add/mod><operand 2>\n";
- write(2, errmsg, strlen(errmsg));
- return false;
- }
- return true;
- }
- void my_calc(char ***argvv, int * acc){
- char msg[1024]; //IDK WHAT TO SET THIS AS BC IDK HOW LONG THE MSG WILL BE
- char * op1str = argvv[0][1];
- char * op2str = argvv[0][3];
- char * operator = argvv[0][2];
- if (check_command(op1str, op2str, operator)){
- int operand1 = atoi(op1str);
- int operand2 = atoi(op2str);
- if (strcmp(operator, "add\0") == 0){
- int sum = operand1 + operand2;
- (*acc) += sum;
- sprintf(msg, "[OK] %d + %d = %d; Acc %d\n", operand1, operand2, sum, *acc);
- write(1, msg, strlen(msg));
- }
- if (strcmp(operator, "mod\0") == 0){
- int mod = operand1 % operand2;
- int div = operand1 / operand2;
- sprintf(msg, "[OK] %d %% %d = %d * %d + %d\n", operand1, operand2, operand2, div, mod);
- write(1, msg, strlen(msg));
- }
- }
- }
- int main(void)
- {
- char ***argvv;
- int command_counter;
- int num_commands;
- int args_counter;
- char *filev[3];
- int bg;
- int ret;
- int standards[3];
- int Acc = 0;
- int status;
- int pid;
- setbuf(stdout, NULL); /* Unbuffered */
- setbuf(stdin, NULL);
- while (1)
- {
- fprintf(stderr, "%s", "msh> "); /* Prompt */
- ret = obtain_order(&argvv, filev, &bg);
- if (ret == 0) break; /* EOF */
- if (ret == -1) continue; /* Syntax error */
- num_commands = ret - 1; /* Line */
- if (num_commands == 0) continue; /* Empty line */
- /*
- * THE PART THAT MUST BE REMOVED STARTS HERE
- * THE FOLLOWING LINES ONLY GIVE AN IDEA OF HOW TO USE THE STRUCTURES
- * argvv AND filev. THESE LINES MUST BE REMOVED.
- */
- //SAVE STANDARDS IN CASE REDIRECTED
- standards[0] = dup(STDIN_FILENO);
- standards[1] = dup(STDOUT_FILENO);
- standards[2] = dup(STDERR_FILENO);
- //REDIRECT STANDARDS IF SPECIFIED
- redirect_standards(filev);
- if(strcmp(argvv[0][0], "mycalc\0") == 0){
- my_calc(argvv, &Acc);
- }
- else{
- int oldp[2];
- int newp[2];
- for(command_counter = 0; command_counter < num_commands; command_counter++){
- // If not last (or only) command in sequence, make a pipe between current process and next process
- if (command_counter < num_commands - 1)
- pipe(newp);
- pid = fork();
- if (pid == 0){
- // If sequence of commands, redirect input/output between processes of each command
- if (num_commands > 1) {
- // If first command in sequence, close read end of next pipe because only writing to it, and
- // redirect standard output to write end of next pipe
- if(command_counter == 0){
- close(newp[0]);
- dup2(newp[1], STDOUT_FILENO);
- }
- // If in between command, close read end of next pipe because only writing to it, and
- // redirect standard input to read end from last pipe and standard output to write end of next pipe
- else if (command_counter > 0 && command_counter < num_commands-1){
- close(newp[0]);
- dup2(oldp[0], STDIN_FILENO);
- dup2(newp[1], STDOUT_FILENO);
- }
- // If in last command, redirect standard read to read from last pipe, and
- // don't redirect standard output to anything
- else{
- dup2(oldp[0], STDIN_FILENO);
- }
- }
- if ((execvp(argvv[command_counter][0], argvv[command_counter]) < 0)){
- perror("ERROR EXECUTING COMMAND");
- exit(-1);
- }
- }
- // If sequence of commands, appropriately manage open file descriptors in parents for pipes in parent process
- if (num_commands > 1){
- // 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
- // save next pipe for use by next process
- if(command_counter == 0){
- close(newp[1]);
- oldp[0] = newp[0];
- oldp[1] = newp[1];
- }
- // If in between command, close read end of last pipe because no longer need it, since already passed off to child process, and
- // close write end of next pipe because process of next command will only read from it, never write to it, and
- // save next pipe for use by next process
- else if (command_counter > 0 && command_counter < num_commands-1){
- close(oldp[0]);
- close(newp[1]);
- oldp[0] = newp[0];
- oldp[1] = newp[1];
- }
- // 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
- else{
- close(oldp[0]);
- close(oldp[1]);
- }
- }
- //BACKGROUND CHECK
- if (bg == 0)
- while(wait(&status) != pid);
- else{
- waitpid(pid, &status, WNOHANG);
- if (command_counter == num_commands -1)
- printf("[%d]\n", pid);
- }
- }
- }
- //RESTORE STANDARDS
- restore_standards(filev, standards);
- /*
- * END OF THE PART TO BE REMOVED
- */
- } //fin while
- return 0;
- } //end main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement