/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* executor.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: sede-san static inline bool can_execute_command(t_command *command, t_minishell *minishell); static inline bool command_exists(t_command *command, t_minishell *minishell); static u_int8_t execute_command(t_command *command, t_minishell *minishell); static u_int8_t execute_command(t_command *command, t_minishell *minishell); // static inline bool is_piped(t_command *command); static void cmdfree(t_command *command); static void cmdfree_argv(char **argv); # define WRITE_PIPE 1 # define READ_PIPE 0 # define CHILD_PID 0 u_int8_t execute( t_list *command_list, t_minishell *minishell ) { t_list *current_command; int prev_read_fd; pid_t pid; u_int8_t exit_status; int child_exit_status; prev_read_fd = -1; exit_status = EXIT_SUCCESS; current_command = command_list; while (current_command != NULL) { t_command *command = (t_command *)current_command->content; int pipefd[2]; /* Create pipe ONLY if there is a next command */ if (current_command->next) { if (pipe(pipefd) == -1) { perror("pipe"); exit_status = EXIT_FAILURE; break ; } } // create fork pid = 0; if (current_command->next != NULL || !is_builtin(command->path, minishell)) pid = fork(); // handle fork error if (pid == -1) { perror("fork"); return (EXIT_FAILURE); } // handle child process if (pid == CHILD_PID) { /* If we have input from previous pipe */ if (prev_read_fd != -1) { dup2(prev_read_fd, STDIN_FILENO); close(prev_read_fd); } /* If we pipe output to next command */ if (current_command->next) { dup2(pipefd[WRITE_PIPE], STDOUT_FILENO); close(pipefd[READ_PIPE]); close(pipefd[WRITE_PIPE]); } execute_command(command, minishell); // child process exits here } // handle parent process waitpid(pid, &child_exit_status, 0); // wait for child to finish if (prev_read_fd != -1) close(prev_read_fd); if (current_command->next) { close(pipefd[WRITE_PIPE]); /* parent does not write */ prev_read_fd = pipefd[READ_PIPE]; /* pass read end forward */ } else prev_read_fd = -1; // continue executing current_command = current_command->next; } ft_lstclear(&command_list, (void (*)(void *))cmdfree); exit_status = child_exit_status; return (exit_status); } static inline bool can_execute_command( t_command *command, t_minishell *minishell ) { if (!is_builtin(command->path, minishell) && access(command->path, X_OK) != EXIT_SUCCESS) return (false); return (true); } static inline bool command_exists( t_command *command, t_minishell *minishell ) { if (!is_builtin(command->path, minishell) && access(command->path, F_OK) != EXIT_SUCCESS) return (false); return (true); } static u_int8_t execute_command( t_command *command, t_minishell *minishell ) { char **envp; t_builtin_func builtin; if (is_builtin(command->path, minishell)) { builtin = ft_hashmap_get(minishell->builtins, command->path); return (builtin(*command, minishell)); } envp = get_envp(minishell); execve(command->path, command->argv, envp); // handle error if execve fails perror("execve"); free_envp(envp); exit(EXIT_FAILURE); } // static inline bool is_piped( // t_command *command // ) { // return (command->piped_to != NULL || command->piped_from != NULL); // } // static u_int8_t handle_child_process( // t_command *command, // t_minishell *minishell // ) { // if (!redirect_pipes(command)) // exit(EXIT_FAILURE); // execute_command(command, minishell); // exit(EXIT_FAILURE); // } // static int redirect_pipe( // int from, // int to // ) { // if (dup2(from, to) == -1) // return (-1); // close(from); // return (0); // } // static int redirect_pipes( // t_command *command // ) { // if (command->piped_from && // redirect_pipe(command->piped_from->outfile, STDIN_FILENO) == -1) // { // perror("dup2"); // return (0); // } // if (command->piped_to && // redirect_pipe(command->outfile, STDOUT_FILENO) == -1) // { // perror("dup2"); // return (0); // } // return (1); // } // static void show_error( // t_command *command, // t_minishell *minishell // ) { // if (!command_exists(command, minishell)) // { // ft_eprintf("minishell: %s: command not found\n", command->argv[0]); // minishell->exit_status = 127; // } // else if (!can_execute_command(command, minishell)) // { // ft_eprintf("minishell: %s: %s\n", command->path, strerror(errno)); // minishell->exit_status = errno; // } // } static void cmdfree( t_command *command ) { if (command == NULL) return ; cmdfree_argv(command->argv); free(command->path); free(command); } static void cmdfree_argv( char **argv ) { size_t i; if (argv == NULL) return ; i = 0; while (argv[i] != NULL) { free(argv[i]); i++; } free(argv); } // static void debug_print_command_info( // t_command *command // ) { // size_t i; // if (command == NULL) // { // printf("Command is NULL\n"); // return ; // } // printf("Command info:\n"); // printf(" Path: %s\n", command->path); // printf(" Argc: %d\n", command->argc); // printf(" Argv:\n"); // for (i = 0; i < (size_t)command->argc; i++) // printf(" arg[%zu]: %s\n", i, command->argv[i]); // printf(" Infile FD: %d\n", command->infile); // printf(" Outfile FD: %d\n", command->outfile); // printf("--------------------------\n"); // }