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 : }