LCOV - code coverage report
Current view: top level - src - scheduler.c (source / functions) Hit Total Coverage
Test: report.info Lines: 57 65 87.7 %
Date: 2024-01-02 12:43:31 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "scheduler.h"
       2             : 
       3          12 : int execute_external_command(const Command *command, int run_in_background) {
       4          12 :     pid_t pid = fork();
       5             : 
       6          24 :     if (pid < 0) {
       7           0 :         perror("fork");
       8           0 :         exit(EXIT_FAILURE);
       9             :     }
      10             : 
      11          24 :     if (pid == CHILD_PROCESS) {
      12          12 :         handle_input_redirection(command);
      13          12 :         handle_output_redirection(command);
      14             : 
      15          12 :         if(execvp(command->command, command->complete_command) < 0) {
      16           0 :             print_perror("%s: command not found. ", command->command);
      17           0 :             exit(EXIT_FAILURE);
      18             :         }
      19             :     }  else {
      20          12 :         if (run_in_background) {
      21           1 :             add_background_process(pid, command);
      22             :         } else {
      23             :             int execution_status;
      24          11 :             waitpid(pid, &execution_status, 0);
      25          11 :             return execution_status;
      26             :         }
      27             :     }
      28             : 
      29           1 :     return 0;
      30             : }
      31             : 
      32             : 
      33          24 : int execute_command(const Command *command, CommandSequence *commandSequence, int run_in_background) {
      34          24 :     if (is_redirection_command(command)) {
      35           4 :         return execute_external_command(command, run_in_background);
      36             :     }
      37             : 
      38          20 :     int execution_status = execute_builtin_command(command, commandSequence);
      39             : 
      40          18 :     if (execution_status == IS_NOT_BUILTIN_COMMAND) {
      41           8 :         execution_status = execute_external_command(command, run_in_background);
      42             :     }
      43             : 
      44          18 :     return execution_status;
      45             : }
      46             : 
      47          20 : int execute_command_sequence(CommandSequence *sequence) {
      48          20 :     int status = 0;
      49          20 :     int is_current_command_failed = 0;
      50          20 :     int is_skipping_next_command = 0;
      51             :     OperatorType current_operator;
      52          20 :     int is_running_in_background = 0;
      53          20 :     const int last_command = sequence->num_commands - 1;
      54             : 
      55          37 :     for (size_t i = 0; i < sequence->num_commands; ++i) {
      56          31 :         is_running_in_background = 0;
      57          31 :         current_operator = UNKNOWN;
      58             : 
      59          31 :         if (is_skipping_next_command) {
      60           6 :             is_skipping_next_command = 0;
      61           6 :             continue;
      62             :         }
      63             : 
      64             :         // Check if operator exist for the current command
      65          25 :         if(sequence->num_operators > i) 
      66             :         {
      67          11 :             current_operator = get_operator_type(sequence->operators[i]);
      68             : 
      69             :             // Before executing the current command, check if it is a pipe or a background operator
      70          11 :             if(current_operator == PIPE && i < last_command) {
      71           1 :                 execute_pipe(&(sequence->commands[i]), &(sequence->commands[i + 1]));
      72           1 :                 is_skipping_next_command = 1;
      73           1 :                 continue; // No need to execute the current command because it is a pipe
      74          10 :             } else if (current_operator == BACKGROUND) {
      75           1 :                 is_running_in_background = 1;
      76             :             }
      77             :         }
      78             : 
      79          24 :         status = execute_command(&(sequence->commands[i]), sequence , is_running_in_background);
      80          22 :         is_current_command_failed = WIFEXITED(status) && WEXITSTATUS(status) == 0;
      81             : 
      82             :         // If the current command is the last one, break the loop because there is no next command
      83          22 :         if (i == last_command) break;
      84             : 
      85          10 :         switch (current_operator) {
      86           2 :             case AND:
      87           2 :                 is_skipping_next_command = (is_current_command_failed == 0);
      88           2 :                 break;
      89           1 :             case OR:
      90           1 :                 is_skipping_next_command = (is_current_command_failed != 0);
      91           1 :                 break;
      92           4 :             case REDIRECTION_APPEND_OUTPUT:
      93             :             case REDIRECTION_APPEND_INPUT:
      94             :             case REDIRECTION_OUTPUT:
      95             :             case REDIRECTION_INPUT:
      96           4 :                 is_skipping_next_command = 1; // Skip the next command because it is a redirection
      97           4 :                 break;
      98           3 :             case SEMICOLON:
      99             :             case PIPE:
     100             :             case BACKGROUND:
     101           3 :                 break; // Continue to the next command
     102           0 :             case UNKNOWN:
     103           0 :                 fprintf(stderr, "Unsupported operator: %s\n", sequence->operators[i]);
     104           0 :                 status = EXIT_FAILURE;
     105           0 :                 break;
     106             :         }
     107          17 :     }
     108             : 
     109          18 :     check_completed_background_processes();
     110             : 
     111          18 :     return status;
     112             : }

Generated by: LCOV version 1.14