LCOV - code coverage report
Current view: top level - src - redirection.c (source / functions) Hit Total Coverage
Test: report.info Lines: 70 89 78.7 %
Date: 2024-01-02 12:43:31 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "redirection.h"
       2             : 
       3          12 : void handle_input_redirection(const Command *command) {
       4          12 :     if (command->redirection.input_file == NULL) return;
       5             : 
       6             :     int in;
       7           2 :     if (command->redirection.append_input) {  // If the "<<" operator was used
       8             :         // Create a temporary file
       9           1 :         in = open("/tmp/redirection_input", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
      10             :         
      11             :         // Read lines from the terminal until the delimiter is encountered
      12             :         char line[256];
      13             :         while (1) {
      14           2 :             printf("> ");  // Print the prompt symbol
      15           2 :             fflush(stdout);  // Ensure the prompt is displayed immediately
      16           2 :             if (fgets(line, sizeof(line), stdin) == NULL) {
      17           0 :                 break;  // End of input
      18             :             }
      19             : 
      20             :             // Remove newline character from the end of the line
      21           2 :             line[strcspn(line, "\n")] = '\0';
      22             : 
      23           2 :             if (strcmp(line, command->redirection.input_file) == 0) {
      24           1 :                 break;  // End of here document
      25             :             }
      26             : 
      27           1 :             write(in, line, strlen(line));
      28           1 :             write(in, "\n", 1);  // Add newline character back when writing to the file
      29             :         }
      30             : 
      31             : 
      32             :         // Close the file and reopen it for reading
      33           1 :         close(in);
      34           1 :         in = open("/tmp/redirection_input", O_RDONLY);
      35             :     } else {  // If the "<" operator was used
      36           1 :         in = open(command->redirection.input_file, O_RDONLY);
      37             :     }
      38           2 :     dup2(in, STDIN_FILENO);
      39           2 :     close(in);
      40             : }
      41             : 
      42          12 : void handle_output_redirection(const Command *command) {
      43          12 :     if (command->redirection.output_file == NULL) return; 
      44             : 
      45             :     int out;
      46           2 :     if (command->redirection.append_output) {  // If the ">>" operator was used
      47           1 :         out = open(command->redirection.output_file, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
      48             :     } else {  // If the ">" operator was used
      49           1 :         out = open(command->redirection.output_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
      50             :     }
      51           2 :     dup2(out, STDOUT_FILENO);
      52           2 :     close(out);
      53             : }
      54             : 
      55          20 : void evaluate_redirection(CommandSequence *sequence) 
      56             : {
      57          31 :     for (int i = 0; i < sequence->num_commands-1; ++i) {
      58          11 :         Command *cmd = &sequence->commands[i];
      59             : 
      60             :         // Get the operator between the current command and the next one
      61          11 :         char *operator = sequence->operators[i];
      62             : 
      63          11 :         if (strcmp(operator, "<") == 0) {
      64             :             // Input redirection
      65           1 :             if (i < sequence->num_commands - 1) {
      66           1 :                 Command *next_cmd = &sequence->commands[i + 1];
      67           1 :                 cmd->redirection.input_file = strdup(next_cmd->command);
      68             :             } else {
      69           0 :                 fprintf(stderr, "Missing command after input redirection\n");
      70           0 :                 break;
      71             :             }
      72          10 :         } else if (strcmp(operator, "<<") == 0) {
      73             :             // Input redirection (append)
      74           1 :             if (i < sequence->num_commands - 1) {
      75           1 :                 Command *next_cmd = &sequence->commands[i + 1];
      76           1 :                 cmd->redirection.input_file = strdup(next_cmd->command);
      77           1 :                 cmd->redirection.append_input = 1;
      78             :             } else {
      79           0 :                 fprintf(stderr, "Missing command after input redirection\n");
      80           0 :                 break;
      81             :             }
      82             :         }
      83           9 :         else if (strcmp(operator, ">") == 0) {
      84             :             // Output redirection
      85           1 :             if (i < sequence->num_commands - 1) {
      86           1 :                 Command *next_cmd = &sequence->commands[i + 1];
      87           1 :                 cmd->redirection.output_file = strdup(next_cmd->command);
      88             :             } else {
      89           0 :                 fprintf(stderr, "Missing command after output redirection\n");
      90           0 :                 break;
      91             :             }
      92           8 :         } else if (strcmp(operator, ">>") == 0) {
      93             :             // Output redirection (append)
      94           1 :             if (i < sequence->num_commands - 1) {
      95           1 :                 Command *next_cmd = &sequence->commands[i + 1];
      96           1 :                 cmd->redirection.output_file = strdup(next_cmd->command);
      97           1 :                 cmd->redirection.append_output = 1;
      98             :             } else {
      99           0 :                 fprintf(stderr, "Missing command after output redirection\n");
     100           0 :                 break;
     101             :             }
     102             :         }
     103             :     }
     104          20 : }
     105             : 
     106          24 : int is_redirection_command(const Command *command) 
     107             : {
     108          24 :     return command->redirection.input_file != NULL || command->redirection.output_file != NULL;
     109             : }
     110             : 
     111           1 : void execute_pipe(Command *cmd1, Command *cmd2) 
     112             : {
     113             :     int pipefd[2];
     114             :     pid_t p1, p2;
     115             : 
     116           1 :     if (pipe(pipefd) < 0) {
     117           0 :         perror("pipe");
     118           0 :         exit(EXIT_FAILURE);
     119             :     }
     120           1 :     p1 = fork();
     121           2 :     if (p1 < 0) {
     122           0 :         perror("fork");
     123           0 :         exit(EXIT_FAILURE);
     124             :     }
     125             : 
     126           2 :     if (p1 == 0) {
     127             :         // Child 1 executing..
     128             :         // It only needs to write at the write end
     129           1 :         close(pipefd[0]);
     130           1 :         dup2(pipefd[1], STDOUT_FILENO);
     131           1 :         close(pipefd[1]);
     132             : 
     133           1 :         if (execvp(cmd1->command, cmd1->complete_command) < 0) {
     134           0 :             perror(cmd1->command);
     135           0 :             exit(EXIT_FAILURE);
     136             :         }
     137             :     } else {
     138             :         // Parent executing
     139           1 :         p2 = fork();
     140             : 
     141           2 :         if (p2 < 0) {
     142           0 :             perror("fork");
     143           0 :             exit(EXIT_FAILURE);
     144             :         }
     145             : 
     146             :         // Child 2 executing..
     147             :         // It only needs to read at the read end
     148           2 :         if (p2 == 0) {
     149           1 :             close(pipefd[1]);
     150           1 :             dup2(pipefd[0], STDIN_FILENO);
     151           1 :             close(pipefd[0]);
     152           1 :             if (execvp(cmd2->command, cmd2->complete_command) < 0) {
     153           0 :                 perror(cmd2->command);
     154           0 :                 exit(EXIT_FAILURE);
     155             :             }
     156             :         } else {
     157             :             // parent executing, waiting for two children
     158           1 :             close(pipefd[0]);
     159           1 :             close(pipefd[1]);
     160           1 :             wait(NULL);
     161           1 :             wait(NULL);
     162             :         }
     163             :     }
     164           3 : }

Generated by: LCOV version 1.14